From c3922e83a93b318ba7ace082fa8b5bed10077e79 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 20 Oct 2023 14:25:33 +0100 Subject: [PATCH] Ensure json query starts with slash to stop crashes. do not fail atari json query not starting with device spec --- lib/device/sio/network.cpp | 38 +++++++++++++++++++++++--------------- lib/fnjson/fnjson.cpp | 14 +++----------- lib/utils/utils.cpp | 7 +++++++ lib/utils/utils.h | 3 +++ 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/lib/device/sio/network.cpp b/lib/device/sio/network.cpp index 696ffbb28..454401427 100755 --- a/lib/device/sio/network.cpp +++ b/lib/device/sio/network.cpp @@ -7,7 +7,10 @@ #include "network.h" #include +#include #include +#include +#include #include "../../include/debug.h" #include "../../include/pinmap.h" @@ -1106,7 +1109,6 @@ void sioNetwork::sio_set_json_query() { uint8_t in[256]; const char *inp = NULL; - uint8_t *tmp; memset(in, 0, sizeof(in)); @@ -1119,22 +1121,28 @@ void sioNetwork::sio_set_json_query() in[i] = 0x00; } - inp = strrchr((const char *)in, ':'); - - if (inp == NULL) - { - sio_error(); - return; + std::string in_string(reinterpret_cast(in)); + size_t last_colon_pos = in_string.rfind(':'); + + std::string inp_string; + if (last_colon_pos != std::string::npos) { + Debug_printf("sioNetwork::sio_set_json_query - skipped device spec. Application should be updated to remove it from query."); + inp_string = in_string.substr(last_colon_pos + 1); + } else { + inp_string = in_string; } - inp++; - json->setReadQuery(string(inp), cmdFrame.aux2); - json_bytes_remaining = json->readValueLen(); - tmp = (uint8_t *)malloc(json->readValueLen()); - json->readValue(tmp,json_bytes_remaining); - *receiveBuffer += string((const char *)tmp,json_bytes_remaining); - free(tmp); - Debug_printf("Query set to %s\n",inp); + json->setReadQuery(inp_string, cmdFrame.aux2); + json_bytes_remaining = json->json_bytes_remaining; + + std::vector tmp(json_bytes_remaining); + json->readValue(tmp.data(), json_bytes_remaining); + + // don't copy past first nul char in tmp + auto null_pos = std::find(tmp.begin(), tmp.end(), 0); + *receiveBuffer += std::string(tmp.begin(), null_pos); + + Debug_printf("Query set to >%s<\r\n", inp_string.c_str()); sio_complete(); } diff --git a/lib/fnjson/fnjson.cpp b/lib/fnjson/fnjson.cpp index 0de040d27..f10f6a330 100644 --- a/lib/fnjson/fnjson.cpp +++ b/lib/fnjson/fnjson.cpp @@ -70,14 +70,6 @@ void FNJSON::setReadQuery(const string &queryString, uint8_t queryParam) _queryString = queryString; _queryParam = queryParam; _item = resolveQuery(); - if (_item == NULL) - { - Debug_printf("FNJSON::setReadQuery resolved item is NULL\r\n"); - } - else - { - Debug_printf("FNJSON::setReadQuery resolved item: %s\r\n", _item->string); - } json_bytes_remaining = readValueLen(); } @@ -86,9 +78,9 @@ void FNJSON::setReadQuery(const string &queryString, uint8_t queryParam) */ cJSON *FNJSON::resolveQuery() { - if (_queryString.empty()) - return _json; - + // Queries must start with a slash, else the JSON parsing crashes FujiNet + // An alternative fix would be to check if the returned value was equal to _json and do something with it, but this is simpler. + _queryString = prependSlash(_queryString); return cJSONUtils_GetPointer(_json, _queryString.c_str()); } diff --git a/lib/utils/utils.cpp b/lib/utils/utils.cpp index 5276e9d88..798d24016 100644 --- a/lib/utils/utils.cpp +++ b/lib/utils/utils.cpp @@ -896,3 +896,10 @@ char *util_hexdump(const void *buf, size_t len) { bool isApproximatelyInteger(double value, double tolerance) { return std::abs(value - std::floor(value)) < tolerance; } + +std::string prependSlash(const std::string& str) { + if (str.empty() || str[0] != '/') { + return "/" + str; + } + return str; +} \ No newline at end of file diff --git a/lib/utils/utils.h b/lib/utils/utils.h index a825ed983..a0c14539f 100644 --- a/lib/utils/utils.h +++ b/lib/utils/utils.h @@ -95,4 +95,7 @@ char *util_hexdump(const void *buf, size_t len); // check if a double is very close to an integer bool isApproximatelyInteger(double value, double tolerance = 1e-6); +// ensure string starts with a "/" +std::string prependSlash(const std::string& str); + #endif // _FN_UTILS_H