Skip to content

Bug in UniversalTelegramBot::getUpdates(): cycling problem when deserializeJson happen to endup with an error #275

@RobertGnz

Description

@RobertGnz

There is a BUG in UniversalTelegramBot::getUpdates() function:

If deserializeJson happen to endup with an error for instance update to big for the buffer, then "last_message_received" is not updated and the function returns 0.
Subsequent calls to getUpdates uses "last_message_received + 1" for the offset value which is passed to getUpdates.
But as last_message_received was not updated, getUpdates will allways read the same message. deserializeJson will always endup with the same error and getUpdates will always return 0.

I propose the following changes in two places of UniversalTelegramBot::getUpdates. To make them easier to find in the code, changes begin with // Robert and ends with // End Robert

Please see below.

int UniversalTelegramBot::getUpdates(long offset) {

#ifdef TELEGRAM_DEBUG
Serial.println(F("GET Update Messages"));
#endif
String command = BOT_CMD("getUpdates?offset=");
command += offset;
command += F("&limit=");
command += HANDLE_MESSAGES;

if (longPoll > 0) {
command += F("&timeout=");
command += String(longPoll);
}
String response = sendGetToTelegram(command); // receive reply from telegram.org

// Robert:
// If deserializeJson happen to endup with an error for instance update to big for
// the buffer, then last_message_received will not be updated.
// Subsequent calls to getUpdates uses last_message_received + 1 for the offset value.
// But as last_message_received was not updated we will allways read the same message.
// Here we try to find the update_id and store it to update last_message_received if necessary.
char * pt1; char * pt2; long candidate;
candidate = -1;
pt1 = strstr_P( response.c_str(), (const char *) F("update_id"));
if ( pt1 != NULL ) {
pt1 = strstr_P( pt1, (const char *) F(":"));
if ( pt1 != NULL ) {
pt1++;
pt2 = strstr_P( pt1, (const char *) F(","));
if ( pt2 != NULL ) {
if ( pt2 - pt1 < 12 ) { // for safety
sscanf( pt1, "%ld", &candidate );
}
}
}
}
// End Robert

if (response == "") {
#ifdef TELEGRAM_DEBUG
Serial.println(F("Received empty string in response!"));
#endif
// close the client as there's nothing to do with an empty string
closeClient();
return 0;
} else {
#ifdef TELEGRAM_DEBUG
Serial.print(F("incoming message length "));
Serial.println(response.length());
Serial.println(F("Creating DynamicJsonBuffer"));
#endif

// Parse response into Json object
DynamicJsonDocument doc(maxMessageLength);
DeserializationError error = deserializeJson(doc, ZERO_COPY(response));
  
if (!error) {
  #ifdef TELEGRAM_DEBUG  
    Serial.print(F("GetUpdates parsed jsonObj: "));
    serializeJson(doc, Serial);
    Serial.println();
  #endif
  if (doc.containsKey("result")) {
    int resultArrayLength = doc["result"].size();
    if (resultArrayLength > 0) {
      int newMessageIndex = 0;
      // Step through all results
      for (int i = 0; i < resultArrayLength; i++) {
        JsonObject result = doc["result"][i];
        if (processResult(result, newMessageIndex)) newMessageIndex++;
      }
      // We will keep the client open because there may be a response to be
      // given
      return newMessageIndex;
    } else {
      #ifdef TELEGRAM_DEBUG  
        Serial.println(F("no new messages"));
      #endif
    }
  } else {
    #ifdef TELEGRAM_DEBUG  
        Serial.println(F("Response contained no 'result'"));
    #endif
  }
} else { // Parsing failed

  // Robert: try to update last_message_received 
  if ( candidate != -1 ) last_message_received = candidate;	  	  
  // End Robert
  
  if (response.length() < 2) { // Too short a message. Maybe a connection issue
    #ifdef TELEGRAM_DEBUG  
        Serial.println(F("Parsing error: Message too short"));
    #endif
  } else {
    // Buffer may not be big enough, increase buffer or reduce max number of
    // messages
    #ifdef TELEGRAM_DEBUG 
        Serial.print(F("Failed to parse update, the message could be too "
                       "big for the buffer. Error code: "));
        Serial.println(error.c_str()); // debug print of parsing error
    #endif     
  }
}
// Close the client as no response is to be given
closeClient();
return 0;

}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions