Skip to content

Commit

Permalink
Fix WebQuery response buffer corruption and format character % (
Browse files Browse the repository at this point in the history
  • Loading branch information
arendst committed Nov 27, 2023
1 parent 3273aaa commit 07031d5
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ All notable changes to this project will be documented in this file.
- Berry parser error in specific cases (#20059)
- ``changeUIntScale`` for linearity when expanding range (#20089)
- ESP32 remove restart energy logging if no energy monitoring is selected
- ``WebQuery`` response buffer corruption and format character ``%`` (#20111)

### Removed

Expand Down
1 change: 1 addition & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
- NeoPool filtration mode display [#19801](https://github.com/arendst/Tasmota/issues/19801)
- Zero-Cross Dimmer for ESP32 with Core3 [#19929](https://github.com/arendst/Tasmota/issues/19929)
- ``changeUIntScale`` for linearity when expanding range [#20089](https://github.com/arendst/Tasmota/issues/20089)
- ``WebQuery`` response buffer corruption and format character ``%`` [#20111](https://github.com/arendst/Tasmota/issues/20111)
- ESP32 I2C allow bus2 support when bus1 is not enabled
- ESP32 remove restart energy logging if no energy monitoring is selected
- ESP32 IR receive with Arduino Core 3 [#19904](https://github.com/arendst/Tasmota/issues/19904)
Expand Down
38 changes: 24 additions & 14 deletions tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino
Original file line number Diff line number Diff line change
Expand Up @@ -447,9 +447,9 @@ const char kUploadErrors[] PROGMEM =

const uint16_t DNS_PORT = 53;
enum HttpOptions { HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER, HTTP_MANAGER_RESET_ONLY };
enum WebCmndStatus { WEBCMND_DONE=0, WEBCMND_WRONG_PARAMETERS, WEBCMND_CONNECT_FAILED, WEBCMND_HOST_NOT_FOUND, WEBCMND_MEMORY_ERROR
enum WebCmndStatus { WEBCMND_DONE, WEBCMND_WRONG_PARAMETERS, WEBCMND_CONNECT_FAILED, WEBCMND_HOST_NOT_FOUND, WEBCMND_MEMORY_ERROR, WEBCMND_VALID_RESPONSE
#ifdef USE_WEBGETCONFIG
, WEBCMND_FILE_NOT_FOUND, WEBCMND_OTHER_HTTP_ERROR, WEBCMND_CONNECTION_LOST, WEBCMND_INVALID_FILE
,WEBCMND_FILE_NOT_FOUND, WEBCMND_OTHER_HTTP_ERROR, WEBCMND_CONNECTION_LOST, WEBCMND_INVALID_FILE
#endif // USE_WEBGETCONFIG
};

Expand Down Expand Up @@ -3353,26 +3353,33 @@ int WebQuery(char *buffer) {
else return status;

if (http_code > 0) { // http_code will be negative on error
if (http_code == HTTP_CODE_OK || http_code == HTTP_CODE_MOVED_PERMANENTLY) {
#ifdef USE_WEBSEND_RESPONSE
if (http_code == HTTP_CODE_OK || http_code == HTTP_CODE_MOVED_PERMANENTLY) {
// Return received data to the user - Adds 900+ bytes to the code
String response = http.getString(); // File found at server - may need lot of ram or trigger out of memory!
const char* read = response.c_str();
ResponseClear();

// uint32_t len = response.length() + 1;
// AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: Response '%*_H' = %s"), len, (uint8_t*)read, read);

Response_P(PSTR("{\"" D_CMND_WEBQUERY "\":"));
char text[2] = { 0 };
char text[3] = { 0 }; // Make room foor double %
text[0] = *read++;
bool assume_json = (text[0] == '{') || (text[0] == '[');
if (!assume_json) { ResponseAppend_P(PSTR("\"")); }
while (text[0] != '\0') {
if (text[0] > 31) { // Remove control characters like linefeed
if ('%' == text[0]) { // Fix char string expansion for %
text[1] = '%';
}
if (assume_json) {
if (ResponseAppend_P(text) == ResponseSize()) { break; };
} else {
if (ResponseAppend_P(EscapeJSONString(text).c_str()) == ResponseSize()) { break; };
}
}
text[0] = *read++;
text[1] = '\0';
}
if (!assume_json) { ResponseAppend_P(PSTR("\"")); }
ResponseJsonEnd();
Expand All @@ -3381,9 +3388,9 @@ int WebQuery(char *buffer) {
// recursive call must be possible in this case
tasm_cmd_activ = 0;
#endif // USE_SCRIPT
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_CMND_WEBQUERY));
status = WEBCMND_VALID_RESPONSE;
} else
#endif // USE_WEBSEND_RESPONSE
}
status = WEBCMND_DONE;
} else {
status = WEBCMND_CONNECT_FAILED;
Expand Down Expand Up @@ -3490,7 +3497,7 @@ bool JsonWebColor(const char* dataBuf)
return true;
}

const char kWebCmndStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND "|" D_JSON_MEMORY_ERROR
const char kWebCmndStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND "|" D_JSON_MEMORY_ERROR "|"
#ifdef USE_WEBGETCONFIG
"|" D_JSON_FILE_NOT_FOUND "|" D_JSON_OTHER_HTTP_ERROR "|" D_JSON_CONNECTION_LOST "|" D_JSON_INVALID_FILE_TYPE
#endif // USE_WEBGETCONFIG
Expand Down Expand Up @@ -3642,17 +3649,20 @@ void CmndWebSend(void)
{
if (XdrvMailbox.data_len > 0) {
uint32_t result = WebSend(XdrvMailbox.data);
char stemp1[20];
ResponseCmndChar(GetTextIndexed(stemp1, sizeof(stemp1), result, kWebCmndStatus));
if (result != WEBCMND_VALID_RESPONSE) {
char stemp1[20];
ResponseCmndChar(GetTextIndexed(stemp1, sizeof(stemp1), result, kWebCmndStatus));
}
}
}

void CmndWebQuery(void)
{
void CmndWebQuery(void) {
if (XdrvMailbox.data_len > 0) {
uint32_t result = WebQuery(XdrvMailbox.data);
char stemp1[20];
ResponseCmndChar(GetTextIndexed(stemp1, sizeof(stemp1), result, kWebCmndStatus));
if (result != WEBCMND_VALID_RESPONSE) {
char stemp1[20];
ResponseCmndChar(GetTextIndexed(stemp1, sizeof(stemp1), result, kWebCmndStatus));
}
}
}

Expand Down

0 comments on commit 07031d5

Please sign in to comment.