--- a/src/json.c Wed Dec 10 22:34:48 2025 +0100 +++ b/src/json.c Wed Dec 10 22:53:41 2025 +0100 @@ -228,7 +228,9 @@ } } - if (ttype != CX_JSON_NO_TOKEN) { + if (ttype == CX_JSON_NO_TOKEN) { + return CX_JSON_NO_DATA; + } else { // uncompleted token size_t uncompleted_len = json->buffer.size - token_part_start; if (json->uncompleted.tokentype == CX_JSON_NO_TOKEN) { @@ -255,9 +257,8 @@ } // advance the buffer position - we saved the stuff in the uncompleted token json->buffer.pos += uncompleted_len; + return CX_JSON_INCOMPLETE_DATA; } - - return CX_JSON_INCOMPLETE_DATA; } // converts a Unicode codepoint to utf8 @@ -804,8 +805,23 @@ // LCOV_EXCL_STOP } CxJsonStatus status = cxJsonNext(&parser, value); + // check if we consume the total string + CxJsonValue *chk_value = NULL; + CxJsonStatus chk_status = CX_JSON_NO_DATA; + if (status == CX_JSON_NO_ERROR) { + chk_status = cxJsonNext(&parser, &chk_value); + } cxJsonDestroy(&parser); - return status; + if (chk_status == CX_JSON_NO_DATA) { + return status; + } else { + cxJsonValueFree(*value); + // if chk_value is nothing, the free is harmless + cxJsonValueFree(chk_value); + *value = &cx_json_value_nothing; + return CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN; + } + } void cxJsonValueFree(CxJsonValue *value) {