diff --git a/mongoose.c b/mongoose.c index c9ff611d95..27583841c5 100644 --- a/mongoose.c +++ b/mongoose.c @@ -5078,15 +5078,18 @@ char *mg_json_get_b64(struct mg_str json, const char *path, int *slen) { char *mg_json_get_hex(struct mg_str json, const char *path, int *slen) { char *result = NULL; int len = 0, off = mg_json_get(json, path, &len); - if (off >= 0 && json.buf[off] == '"' && len > 1 && + if (off >= 0 && json.buf[off] == '"' && len > 1 && (len - 2) % 2 == 0 && (result = (char *) mg_calloc(1, (size_t) len / 2)) != NULL) { int i; for (i = 0; i < len - 2; i += 2) { - mg_str_to_num(mg_str_n(json.buf + off + 1 + i, 2), 16, &result[i >> 1], - sizeof(uint8_t)); + if (!mg_str_to_num(mg_str_n(json.buf + off + 1 + i, 2), 16, + &result[i >> 1], sizeof(uint8_t))) break; + } + if (i < len - 2) mg_free(result), result = NULL; + if (result != NULL) { + result[len / 2 - 1] = '\0'; + if (slen != NULL) *slen = len / 2 - 1; } - result[len / 2 - 1] = '\0'; - if (slen != NULL) *slen = len / 2 - 1; } return result; } diff --git a/mongoose.h b/mongoose.h index 3855e37107..abb56b7375 100644 --- a/mongoose.h +++ b/mongoose.h @@ -4104,7 +4104,7 @@ char *mg_json_get_str(struct mg_str json, const char *path); // Decodes a hex-encoded JSON string at path into a heap-allocated byte array. // Sets *len to the decoded byte count. Caller must mg_free() the result. -// Returns NULL if not found or not a string. +// Returns NULL if not found, not a string, or not valid hexadecimal. char *mg_json_get_hex(struct mg_str json, const char *path, int *len); // Decodes a base64-encoded JSON string at path into a heap-allocated byte diff --git a/src/json.c b/src/json.c index d014eb83f2..8b75d0924b 100644 --- a/src/json.c +++ b/src/json.c @@ -363,15 +363,18 @@ char *mg_json_get_b64(struct mg_str json, const char *path, int *slen) { char *mg_json_get_hex(struct mg_str json, const char *path, int *slen) { char *result = NULL; int len = 0, off = mg_json_get(json, path, &len); - if (off >= 0 && json.buf[off] == '"' && len > 1 && + if (off >= 0 && json.buf[off] == '"' && len > 1 && (len - 2) % 2 == 0 && (result = (char *) mg_calloc(1, (size_t) len / 2)) != NULL) { int i; for (i = 0; i < len - 2; i += 2) { - mg_str_to_num(mg_str_n(json.buf + off + 1 + i, 2), 16, &result[i >> 1], - sizeof(uint8_t)); + if (!mg_str_to_num(mg_str_n(json.buf + off + 1 + i, 2), 16, + &result[i >> 1], sizeof(uint8_t))) break; + } + if (i < len - 2) mg_free(result), result = NULL; + if (result != NULL) { + result[len / 2 - 1] = '\0'; + if (slen != NULL) *slen = len / 2 - 1; } - result[len / 2 - 1] = '\0'; - if (slen != NULL) *slen = len / 2 - 1; } return result; } diff --git a/src/json.h b/src/json.h index 6e06c63c4d..0557ef650a 100644 --- a/src/json.h +++ b/src/json.h @@ -57,7 +57,7 @@ char *mg_json_get_str(struct mg_str json, const char *path); // Decodes a hex-encoded JSON string at path into a heap-allocated byte array. // Sets *len to the decoded byte count. Caller must mg_free() the result. -// Returns NULL if not found or not a string. +// Returns NULL if not found, not a string, or not valid hexadecimal. char *mg_json_get_hex(struct mg_str json, const char *path, int *len); // Decodes a base64-encoded JSON string at path into a heap-allocated byte diff --git a/test/unit_test.c b/test/unit_test.c index e08c75a687..c270385cfb 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -3741,13 +3741,23 @@ static void test_json(void) { ASSERT(b == true); ASSERT(mg_json_get(json, "$.b[2]", &len) < 0); - json = mg_str("[\"YWJj\", \"0100026869\"]"); + json = mg_str("[\"YWJj\", \"0100026869\", \"\", \"abc\", \"0g\"]"); ASSERT((str = mg_json_get_b64(json, "$[0]", &len)) != NULL); ASSERT(len == 3 && memcmp(str, "abc", (size_t) len) == 0); mg_free(str); ASSERT((str = mg_json_get_hex(json, "$[1]", &len)) != NULL); ASSERT(len == 5 && memcmp(str, "\x01\x00\x02hi", (size_t) len) == 0); mg_free(str); + ASSERT((str = mg_json_get_hex(json, "$[2]", &len)) != NULL); + ASSERT(len == 0 && str[0] == '\0'); + mg_free(str); + len = 42; + str = mg_json_get_hex(json, "$[3]", &len); + ASSERT(str == NULL && len == 42); + mg_free(str); + str = mg_json_get_hex(json, "$[4]", &len); + ASSERT(str == NULL && len == 42); + mg_free(str); json = mg_str("{\"a\":[1,2,3], \"ab\": 2}"); ASSERT(mg_json_get_long(json, "$.a[0]", -42) == 1);