Explorar o código

refactor: 完善模糊测试覆盖率

RyanCW hai 1 mes
pai
achega
0b97df28fc
Modificáronse 5 ficheiros con 203 adicións e 151 borrados
  1. 136 129
      RyanJson/RyanJson.c
  2. 4 2
      RyanJson/RyanJson.h
  3. 8 12
      RyanJson/RyanJsonUtils.c
  4. 52 8
      test/fuzzer/RyanJsonFuzzer.c
  5. 3 0
      test/fuzzer/RyanJsonFuzzer.dict

+ 136 - 129
RyanJson/RyanJson.c

@@ -71,6 +71,17 @@ typedef struct
 #define RyanJsonAlign(size, align)     (((size) + (align) - 1) & ~((align) - 1))
 #define RyanJsonAlignDown(size, align) ((size) & ~((align) - 1))
 #define _checkType(info, type)         ((info) == (type))
+#define RyanJsonUnused(x)              (void)(x)
+
+#ifdef RyanJsonEnableAssert
+#define RyanJsonCheckNeverNoAssert(EX)                                                                                                     \
+	do                                                                                                                                 \
+	{                                                                                                                                  \
+		if (!(EX)) RyanJsonAssert(NULL && #EX);                                                                                    \
+	} while (0)
+#else
+#define RyanJsonCheckNeverNoAssert(EX) (void)(EX)
+#endif
 
 /**
  * @brief printBuf相关宏
@@ -116,7 +127,7 @@ static inline RyanJsonBool_e parseBufTyrAdvanceCurrentPrt(RyanJsonParseBuffer *p
 #ifdef isEnableFuzzer
 	static uint32_t count = 0;
 	count++;
-	if (0 == count % RyanJsonRandRange(10, 2000)) { return RyanJsonFalse; }
+	RyanJsonCheckReturnFalse(0 != count % RyanJsonRandRange(10, 2000));
 #endif
 
 	if (parseBufHasRemainBytes(parseBuf, bytesToAdvance))
@@ -139,9 +150,9 @@ static RyanJsonBool_e parseBufSkipWhitespace(RyanJsonParseBuffer *parseBuf)
 	RyanJsonCheckAssert(NULL != parseBuf);
 
 #ifdef isEnableFuzzer
-	static uint32_t count = 0;
-	count++;
-	if (0 == count % RyanJsonRandRange(10, 2000)) { return RyanJsonFalse; }
+	static uint32_t jsonskipCount = 1;
+	jsonskipCount++;
+	RyanJsonCheckReturnFalse(0 != jsonskipCount % RyanJsonRandRange(10, 2000));
 #endif
 
 	const uint8_t *cursor = parseBuf->currentPtr;
@@ -248,7 +259,9 @@ static inline void *RyanJsonGetValue(RyanJson_t pJson)
 	RyanJsonCheckAssert(NULL != pJson);
 
 	uint32_t len = RyanJsonFlagSize;
-	if (RyanJsonIsKey(pJson) || RyanJsonIsString(pJson))
+	//? 目前的场景不会发生 RyanJsonIsKey(pJson) 为false的情况
+	// if (RyanJsonIsKey(pJson) || RyanJsonIsString(pJson))
+	if (RyanJsonIsKey(pJson))
 	{
 		len += RyanJsonGetInlineStringSize;
 		// jsonLog(" keyLen: %d, keyLenField: %d, \r\n", RyanJsonGetKeyLen(pJson),
@@ -268,17 +281,15 @@ static inline void *RyanJsonGetValue(RyanJson_t pJson)
  */
 static void *RyanJsonExpandRealloc(void *block, uint32_t oldSize, uint32_t newSize)
 {
+	// 不考虑 block 为空的情况
 	RyanJsonCheckAssert(NULL != block);
 	if (NULL != jsonRealloc) { return jsonRealloc(block, newSize); }
 
 	void *newBlock = jsonMalloc(newSize);
 	RyanJsonCheckReturnNull(NULL != newBlock);
 
-	if (NULL != block)
-	{
-		RyanJsonMemcpy(newBlock, block, oldSize);
-		jsonFree(block);
-	}
+	RyanJsonMemcpy(newBlock, block, oldSize);
+	jsonFree(block);
 	return newBlock;
 }
 
@@ -430,7 +441,7 @@ static RyanJsonBool_e RyanJsonChangeString(RyanJson_t pJson, RyanJsonBool_e isNe
 	{
 		// 申请新的空间
 		uint8_t *newPtr = (uint8_t *)jsonMalloc(mallocSize);
-		if (NULL == newPtr) { return RyanJsonFalse; }
+		RyanJsonCheckReturnFalse(NULL != newPtr);
 
 		// 先赋值,因为 RyanJsonSetHiddePrt 可能会覆盖key和string的空间
 		if (NULL != key)
@@ -510,24 +521,20 @@ static RyanJson_t RyanJsonNewNode(RyanJsonNodeInfo_t *info)
 	if (NULL != info->key || _checkType(info->type, RyanJsonTypeString)) { size += RyanJsonGetInlineStringSize; }
 
 	RyanJson_t pJson = (RyanJson_t)jsonMalloc((size_t)size);
-	if (NULL != pJson)
-	{
-		// 只清空结构体就行了
-		RyanJsonMemset(pJson, 0, size); // 这个size很小,没有优化的必要,直接memset吧
+	RyanJsonCheckReturnNull(NULL != pJson);
 
-		RyanJsonSetType(pJson, info->type);
+	// 只清空结构体就行了
+	RyanJsonMemset(pJson, 0, size); // 这个size很小,没有优化的必要,直接memset吧
 
-		RyanJsonCheckCode(RyanJsonTrue == RyanJsonChangeString(pJson, RyanJsonTrue, info->key, info->strValue), {
-			jsonFree(pJson);
-			return NULL;
-		});
+	RyanJsonSetType(pJson, info->type);
 
-		if (_checkType(info->type, RyanJsonTypeBool)) { RyanJsonSetPayloadBoolValueByFlag(pJson, info->boolIsTrueFlag); }
-		else if (_checkType(info->type, RyanJsonTypeNumber))
-		{
-			RyanJsonSetPayloadNumberIsDoubleByFlag(pJson, info->numberIsDoubleFlag);
-		}
-	}
+	RyanJsonCheckCode(RyanJsonTrue == RyanJsonChangeString(pJson, RyanJsonTrue, info->key, info->strValue), {
+		jsonFree(pJson);
+		return NULL;
+	});
+
+	if (_checkType(info->type, RyanJsonTypeBool)) { RyanJsonSetPayloadBoolValueByFlag(pJson, info->boolIsTrueFlag); }
+	else if (_checkType(info->type, RyanJsonTypeNumber)) { RyanJsonSetPayloadNumberIsDoubleByFlag(pJson, info->numberIsDoubleFlag); }
 
 	return pJson;
 }
@@ -682,10 +689,7 @@ void RyanJsonDelete(RyanJson_t pJson)
  *
  * @param block
  */
-void RyanJsonFree(void *block)
-{
-	if (block) { jsonFree(block); }
-}
+void RyanJsonFree(void *block) { jsonFree(block); }
 
 /**
  * @brief 从字符串中获取十六进制值
@@ -745,23 +749,24 @@ static RyanJsonBool_e RyanJsonParseNumber(RyanJsonParseBuffer *parseBuf, char *k
 {
 	RyanJsonCheckAssert(NULL != parseBuf && NULL != out);
 
-	double number = 0.0;
-	int32_t sign = 1;
+	double number = 0;
 	int32_t scale = 0;
 	int32_t e_sign = 1;
 	int32_t e_scale = 0;
-	RyanJsonBool_e isint = RyanJsonTrue;
+	RyanJsonBool_e isNegative = RyanJsonFalse;
+	RyanJsonBool_e isInt = RyanJsonTrue;
 
 	// 处理符号
-	if (parseBufHasRemain(parseBuf) && '-' == *parseBuf->currentPtr)
+	if ('-' == *parseBuf->currentPtr)
 	{
-		sign = -1;
-		RyanJsonCheckReturnFalse(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 1));
+		isNegative = RyanJsonTrue;
+		// 这个不会失败因为进来前已经判断过 parseBufHasRemain(parseBuf)
+		RyanJsonCheckNeverNoAssert(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 1));
 		RyanJsonCheckReturnFalse(parseBufHasRemain(parseBuf) && *parseBuf->currentPtr >= '0' && *parseBuf->currentPtr <= '9');
 	}
 
 	// 跳过前导零
-	while (parseBufHasRemain(parseBuf) && '0' == *parseBuf->currentPtr)
+	while ('0' == *parseBuf->currentPtr)
 	{
 		RyanJsonCheckReturnFalse(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 1));
 		// 前导0后面不允许跟数组,比如"0123"
@@ -787,7 +792,7 @@ static RyanJsonBool_e RyanJsonParseNumber(RyanJsonParseBuffer *parseBuf, char *k
 			scale--; // 每读一位小数,scale减一
 			RyanJsonCheckReturnFalse(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 1));
 		}
-		isint = RyanJsonFalse;
+		isInt = RyanJsonFalse;
 	}
 
 	// 指数部分
@@ -804,20 +809,20 @@ static RyanJsonBool_e RyanJsonParseNumber(RyanJsonParseBuffer *parseBuf, char *k
 			e_scale = e_scale * 10 + (*parseBuf->currentPtr - '0');
 			RyanJsonCheckReturnFalse(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 1));
 		}
-		isint = RyanJsonFalse;
+		isInt = RyanJsonFalse;
 	}
 
+	// 判断符号
+	if (RyanJsonTrue == isNegative) { number = -number; }
+
 	// 创建 JSON 节点
 	RyanJson_t newItem = NULL;
-	if (RyanJsonTrue == isint && number >= INT32_MIN && number <= INT32_MAX)
-	{
-		newItem = RyanJsonCreateInt(key, (int32_t)(sign * number));
-	}
+	if (RyanJsonTrue == isInt && number >= INT32_MIN && number <= INT32_MAX) { newItem = RyanJsonCreateInt(key, (int32_t)number); }
 	else
 	{
 		// 避免 pow 调用过多,直接计算指数
 		double expFactor = pow(10.0, scale + e_sign * e_scale);
-		newItem = RyanJsonCreateDouble(key, sign * number * expFactor);
+		newItem = RyanJsonCreateDouble(key, number * expFactor);
 	}
 
 	RyanJsonCheckReturnFalse(NULL != newItem);
@@ -870,7 +875,8 @@ static RyanJsonBool_e RyanJsonParseStringBuffer(RyanJsonParseBuffer *parseBuf, c
 	RyanJsonCheckReturnFalse(NULL != outBuffer);
 
 	uint8_t *outCurrentPtr = outBuffer;
-	while (parseBufHasRemain(parseBuf) && '\"' != *parseBuf->currentPtr)
+	// ?获取字符串长度的时候已经确保 '\"' != *parseBuf->currentPtr 一定有结尾了
+	while ('\"' != *parseBuf->currentPtr)
 	{
 		// 普通字符
 		if ('\\' != *parseBuf->currentPtr)
@@ -899,60 +905,58 @@ static RyanJsonBool_e RyanJsonParseStringBuffer(RyanJsonParseBuffer *parseBuf, c
 			// 获取 Unicode 字符
 			uint64_t codepoint = 0;
 			RyanJsonCheckCode(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 4), { goto error__; });
-			uint32_t first_code = 0;
-			RyanJsonCheckCode(RyanJsonTrue == RyanJsonParseHex(parseBuf->currentPtr - 3, &first_code), { goto error__; });
+			uint32_t firstCode = 0;
+			RyanJsonCheckCode(RyanJsonTrue == RyanJsonParseHex(parseBuf->currentPtr - 3, &firstCode), { goto error__; });
 			// 检查是否有效
-			if (first_code >= 0xDC00 && first_code <= 0xDFFF) { goto error__; }
+			RyanJsonCheckCode(firstCode < 0xDC00 || firstCode > 0xDFFF, { goto error__; });
 
-			if (first_code >= 0xD800 && first_code <= 0xDBFF) // UTF16 代理对
+			if (firstCode >= 0xD800 && firstCode <= 0xDBFF) // UTF16 代理对
 			{
-				if (!parseBufHasRemainAtIndex(parseBuf, 2)) { goto error__; }
+				RyanJsonCheckCode(parseBufHasRemainAtIndex(parseBuf, 2), { goto error__; });
 
-				if (parseBuf->currentPtr[1] != '\\' || parseBuf->currentPtr[2] != 'u')
-				{
+				RyanJsonCheckCode('\\' == parseBuf->currentPtr[1] && 'u' == parseBuf->currentPtr[2], {
 					goto error__; // 缺少代理的后半部分
-				}
+				});
 
 				RyanJsonCheckCode(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 6), { goto error__; });
-				uint32_t second_code = 0;
-				RyanJsonCheckCode(RyanJsonTrue == RyanJsonParseHex(parseBuf->currentPtr - 3, &second_code),
-						  { goto error__; });
-				if (0 == first_code || second_code < 0xDC00 || second_code > 0xDFFF)
-				{
+				uint32_t secondCode = 0;
+				// 上面已经判断过,这个不应该失败
+				RyanJsonCheckNeverNoAssert(RyanJsonTrue == RyanJsonParseHex(parseBuf->currentPtr - 3, &secondCode));
+				RyanJsonCheckCode(secondCode >= 0xDC00 && secondCode <= 0xDFFF, {
 					goto error__; // 无效的代理后半部分
-				}
+				});
 
-				codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
+				codepoint = 0x10000 + (((firstCode & 0x3FF) << 10) | (secondCode & 0x3FF));
 			}
 			else
 			{
-				codepoint = first_code;
+				codepoint = firstCode;
 			}
 
 			/* encode as UTF-8
 			 * takes at maximum 4 bytes to encode:
 			 * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
-			uint8_t utf8_length;
-			uint8_t first_byte_mark;
+			uint8_t utf8Length;
+			uint8_t firstByteMark;
 			if (codepoint < 0x80)
 			{
-				utf8_length = 1; // normal ascii, encoding 0xxxxxxx
-				first_byte_mark = 0;
+				utf8Length = 1; // normal ascii, encoding 0xxxxxxx
+				firstByteMark = 0;
 			}
 			else if (codepoint < 0x800)
 			{
-				utf8_length = 2;        // two bytes, encoding 110xxxxx 10xxxxxx
-				first_byte_mark = 0xC0; // 11000000
+				utf8Length = 2;       // two bytes, encoding 110xxxxx 10xxxxxx
+				firstByteMark = 0xC0; // 11000000
 			}
 			else if (codepoint < 0x10000)
 			{
-				utf8_length = 3;        // three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx
-				first_byte_mark = 0xE0; // 11100000
+				utf8Length = 3;       // three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx
+				firstByteMark = 0xE0; // 11100000
 			}
 			else
 			{
-				utf8_length = 4;        // four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx
-				first_byte_mark = 0xF0; // 11110000
+				utf8Length = 4;       // four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx
+				firstByteMark = 0xF0; // 11110000
 			}
 			// 不太可能发生
 			// else
@@ -961,19 +965,19 @@ static RyanJsonBool_e RyanJsonParseStringBuffer(RyanJsonParseBuffer *parseBuf, c
 			// }
 
 			// encode as utf8
-			for (uint8_t utf8_position = (uint8_t)(utf8_length - 1); utf8_position > 0; utf8_position--)
+			for (uint8_t utf8Position = (uint8_t)(utf8Length - 1); utf8Position > 0; utf8Position--)
 			{
-				outCurrentPtr[utf8_position] = (uint8_t)((codepoint | 0x80) & 0xBF); // 10xxxxxx
+				outCurrentPtr[utf8Position] = (uint8_t)((codepoint | 0x80) & 0xBF); // 10xxxxxx
 				codepoint >>= 6;
 			}
 
 			// encode first byte
-			if (utf8_length > 1) { outCurrentPtr[0] = (uint8_t)((codepoint | first_byte_mark) & 0xFF); }
+			if (utf8Length > 1) { outCurrentPtr[0] = (uint8_t)((codepoint | firstByteMark) & 0xFF); }
 			else
 			{
 				outCurrentPtr[0] = (uint8_t)(codepoint & 0x7F);
 			}
-			outCurrentPtr += utf8_length;
+			outCurrentPtr += utf8Length;
 			break;
 		}
 
@@ -986,12 +990,9 @@ static RyanJsonBool_e RyanJsonParseStringBuffer(RyanJsonParseBuffer *parseBuf, c
 	}
 	*outCurrentPtr = '\0';
 
-	// todo 不等于的话是不是应该报错?
-	if (parseBufHasRemain(parseBuf) && *parseBuf->currentPtr == '\"')
-	{
-		RyanJsonCheckCode(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 1), { goto error__; });
-	}
+	RyanJsonCheckNeverNoAssert('\"' == *parseBuf->currentPtr);
 
+	RyanJsonCheckCode(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 1), { goto error__; });
 	*buffer = (char *)outBuffer;
 	return RyanJsonTrue;
 
@@ -1043,7 +1044,7 @@ static RyanJsonBool_e RyanJsonParseArray(RyanJsonParseBuffer *parseBuf, char *ke
 	RyanJsonCheckReturnFalse(NULL != newItem);
 
 	RyanJson_t prev = NULL, item;
-	RyanJsonCheckCode(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 1), { goto error__; });
+	RyanJsonCheckNeverNoAssert(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 1));
 	RyanJsonCheckCode(RyanJsonTrue == parseBufSkipWhitespace(parseBuf), { goto error__; });
 
 	// 空数组
@@ -1060,9 +1061,9 @@ static RyanJsonBool_e RyanJsonParseArray(RyanJsonParseBuffer *parseBuf, char *ke
 
 		RyanJsonCheckCode(RyanJsonTrue == parseBufSkipWhitespace(parseBuf), { goto error__; });
 
-		if (RyanJsonFalse == RyanJsonParseValue(parseBuf, NULL, &item)) { goto error__; }
+		RyanJsonCheckCode(RyanJsonTrue == RyanJsonParseValue(parseBuf, NULL, &item), { goto error__; });
 
-		RyanJsonCheckAssert(RyanJsonTrue == RyanJsonInsert(newItem, UINT32_MAX, item));
+		RyanJsonCheckNeverNoAssert(RyanJsonTrue == RyanJsonInsert(newItem, UINT32_MAX, item));
 
 		prev = item;
 
@@ -1100,7 +1101,7 @@ static RyanJsonBool_e RyanJsonParseObject(RyanJsonParseBuffer *parseBuf, char *k
 	RyanJsonCheckReturnFalse(NULL != newItem);
 
 	RyanJson_t prev = NULL, item;
-	RyanJsonCheckCode(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 1), { goto error__; });
+	RyanJsonCheckNeverNoAssert(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 1));
 	RyanJsonCheckCode(RyanJsonTrue == parseBufSkipWhitespace(parseBuf), { goto error__; });
 
 	RyanJsonCheckCode(parseBufHasRemain(parseBuf), { goto error__; });
@@ -1115,7 +1116,8 @@ static RyanJsonBool_e RyanJsonParseObject(RyanJsonParseBuffer *parseBuf, char *k
 
 		RyanJsonCheckCode(RyanJsonTrue == parseBufSkipWhitespace(parseBuf), { goto error__; });
 
-		if (RyanJsonFalse == RyanJsonParseStringBuffer(parseBuf, &objKey)) { goto error__; }
+		RyanJsonCheckCode(RyanJsonTrue == RyanJsonParseStringBuffer(parseBuf, &objKey), { goto error__; });
+		RyanJsonCheckNeverNoAssert(NULL != objKey);
 
 		RyanJsonCheckCode(RyanJsonTrue == parseBufSkipWhitespace(parseBuf), { goto error__; });
 
@@ -1125,14 +1127,11 @@ static RyanJsonBool_e RyanJsonParseObject(RyanJsonParseBuffer *parseBuf, char *k
 		RyanJsonCheckCode(RyanJsonTrue == parseBufTyrAdvanceCurrentPrt(parseBuf, 1), { goto error__; });
 		RyanJsonCheckCode(RyanJsonTrue == parseBufSkipWhitespace(parseBuf), { goto error__; });
 
-		if (RyanJsonFalse == RyanJsonParseValue(parseBuf, objKey, &item)) { goto error__; }
-		if (objKey)
-		{
-			jsonFree(objKey);
-			objKey = NULL;
-		}
+		RyanJsonCheckCode(RyanJsonTrue == RyanJsonParseValue(parseBuf, objKey, &item), { goto error__; });
+		jsonFree(objKey);
+		objKey = NULL;
 
-		RyanJsonCheckAssert(RyanJsonTrue == RyanJsonInsert(newItem, UINT32_MAX, item));
+		RyanJsonCheckNeverNoAssert(RyanJsonTrue == RyanJsonInsert(newItem, UINT32_MAX, item));
 
 		prev = item;
 
@@ -1273,14 +1272,14 @@ static RyanJsonBool_e RyanJsonPrintNumber(RyanJson_t pJson, RyanJsonPrintBuffer
 {
 	RyanJsonCheckAssert(NULL != pJson && NULL != printfBuf);
 
-	double numberValue;
 	int32_t len;
 
 	// RyanJsonNumber 类型是一个整数
 	if (RyanJsonFalse == RyanJsonGetPayloadNumberIsDoubleByFlag(pJson))
 	{
 		// RyanJsonCheckReturnFalse(printBufAppend(buf, 21)); // 64 位整数最多包含  20 个数字字符、1 符号
-		RyanJsonCheckReturnFalse(printBufAppend(printfBuf, 11)); // 32 位整数最多包含  10 个数字字符、1 符号
+		// INT32_MIN = -2147483648 (11 chars)
+		RyanJsonCheckReturnFalse(printBufAppend(printfBuf, 11));
 
 		len = RyanJsonSnprintf((char *)printBufCurrentPtr(printfBuf), printfBuf->size, "%" PRId32, RyanJsonGetIntValue(pJson));
 		RyanJsonCheckReturnFalse(len > 0); // snprintf 失败
@@ -1289,32 +1288,33 @@ static RyanJsonBool_e RyanJsonPrintNumber(RyanJson_t pJson, RyanJsonPrintBuffer
 	else // RyanJsonNumber 的类型是浮点型
 	{
 		RyanJsonCheckReturnFalse(printBufAppend(printfBuf, 64)); // 浮点数用64可以适应大部分情况
-		numberValue = RyanJsonGetDoubleValue(pJson);
+		double doubleValue = RyanJsonGetDoubleValue(pJson);
 
 		// use full transformation within bounded space
-		if (fabs(floor(numberValue) - numberValue) <= DBL_EPSILON && fabs(numberValue) < 1.0e60)
+		if (fabs(floor(doubleValue) - doubleValue) <= DBL_EPSILON && fabs(doubleValue) < 1.0e60)
 		{
-			len = RyanJsonSnprintf((char *)printBufCurrentPtr(printfBuf), printfBuf->size, "%.1lf", numberValue);
-			RyanJsonCheckReturnFalse(len > 0); // snprintf 失败
+			len = RyanJsonSnprintf((char *)printBufCurrentPtr(printfBuf), printfBuf->size, "%.1lf", doubleValue);
 		}
 
 		// use exponential form conversion beyond the limited range
-		else if (fabs(numberValue) < 1.0e-6 || fabs(numberValue) > 1.0e9)
+		else if (fabs(doubleValue) < 1.0e-6 || fabs(doubleValue) > 1.0e9)
 		{
-			len = RyanJsonSnprintf((char *)printBufCurrentPtr(printfBuf), printfBuf->size, "%e", numberValue);
-			RyanJsonCheckReturnFalse(len > 0); // snprintf 失败
+			len = RyanJsonSnprintf((char *)printBufCurrentPtr(printfBuf), printfBuf->size, "%e", doubleValue);
 		}
 
 		// default conversion
 		else
 		{
-			len = RyanJsonSnprintf((char *)printBufCurrentPtr(printfBuf), printfBuf->size, "%lf", numberValue);
-			RyanJsonCheckReturnFalse(len > 0); // snprintf 失败
-			while (len > 0 && printBufCurrentPtr(printfBuf)[len - 1] == '0' &&
-			       printBufCurrentPtr(printfBuf)[len - 2] != '.') // 删除小数部分中无效的 0
-			{
-				len--;
-			}
+			len = RyanJsonSnprintf((char *)printBufCurrentPtr(printfBuf), printfBuf->size, "%lf", doubleValue);
+		}
+
+		RyanJsonCheckReturnFalse(len > 0); // snprintf 失败
+
+		// 删除小数部分中无效的 0
+		while (len >= 3)
+		{
+			if ('0' != printBufCurrentPtr(printfBuf)[len - 1] && '.' != printBufCurrentPtr(printfBuf)[len - 2]) { break; }
+			len--;
 		}
 		printfBuf->cursor += (uint32_t)len;
 	}
@@ -1735,12 +1735,14 @@ RyanJson_t RyanJsonGetObjectByKey(RyanJson_t pJson, const char *key)
 	RyanJsonCheckReturnNull(_checkType(RyanJsonGetType(pJson), RyanJsonTypeObject));
 
 	RyanJson_t nextItem = RyanJsonGetObjectValue(pJson);
-	RyanJsonCheckReturnNull(NULL != nextItem && RyanJsonIsKey(nextItem));
+	RyanJsonCheckReturnNull(NULL != nextItem);
+	RyanJsonCheckNeverNoAssert(RyanJsonIsKey(nextItem));
 
 	while (0 != RyanJsonStrcmp(RyanJsonGetKey(nextItem), key))
 	{
 		nextItem = nextItem->next;
-		RyanJsonCheckReturnNull(NULL != nextItem && RyanJsonIsKey(nextItem));
+		RyanJsonCheckReturnNull(NULL != nextItem);
+		RyanJsonCheckNeverNoAssert(RyanJsonIsKey(nextItem));
 	}
 
 	return nextItem;
@@ -1796,14 +1798,16 @@ RyanJson_t RyanJsonDetachByKey(RyanJson_t pJson, const char *key)
 	RyanJsonCheckReturnNull(_checkType(RyanJsonGetType(pJson), RyanJsonTypeObject));
 
 	RyanJson_t nextItem = RyanJsonGetObjectValue(pJson);
-	RyanJsonCheckReturnNull(NULL != nextItem && RyanJsonIsKey(nextItem));
+	RyanJsonCheckReturnNull(NULL != nextItem);
+	RyanJsonCheckNeverNoAssert(RyanJsonIsKey(nextItem));
 
 	RyanJson_t prev = NULL;
 	while (0 != RyanJsonStrcmp(RyanJsonGetKey(nextItem), key))
 	{
 		prev = nextItem;
 		nextItem = nextItem->next;
-		RyanJsonCheckReturnNull(NULL != nextItem && RyanJsonIsKey(nextItem));
+		RyanJsonCheckReturnNull(NULL != nextItem);
+		RyanJsonCheckNeverNoAssert(RyanJsonIsKey(nextItem));
 	}
 
 	if (NULL != prev) { prev->next = nextItem->next; }
@@ -1963,16 +1967,17 @@ RyanJsonBool_e RyanJsonReplaceByKey(RyanJson_t pJson, const char *key, RyanJson_
 	RyanJsonCheckReturnFalse(_checkType(RyanJsonGetType(pJson), RyanJsonTypeObject));
 
 	RyanJson_t prev = NULL;
-	// todo 增加nextItem没有key的测试
 	RyanJson_t nextItem = RyanJsonGetObjectValue(pJson);
-	RyanJsonCheckReturnFalse(NULL != nextItem && RyanJsonIsKey(nextItem));
+	RyanJsonCheckReturnFalse(NULL != nextItem);
+	RyanJsonCheckNeverNoAssert(RyanJsonIsKey(nextItem));
 
 	// 找到要修改的节点
 	while (0 != RyanJsonStrcmp(RyanJsonGetKey(nextItem), key))
 	{
 		prev = nextItem;
 		nextItem = nextItem->next;
-		RyanJsonCheckReturnFalse(NULL != nextItem && RyanJsonIsKey(nextItem));
+		RyanJsonCheckReturnFalse(NULL != nextItem);
+		RyanJsonCheckNeverNoAssert(RyanJsonIsKey(nextItem));
 	}
 
 	// 没有key的对象 申请一个带key的对象
@@ -2167,9 +2172,13 @@ RyanJson_t RyanJsonDuplicate(RyanJson_t pJson)
 		break;
 
 	case RyanJsonTypeNumber:
-		// 不可能出现另外一个条件了
 		if (RyanJsonIsInt(pJson)) { newItem = RyanJsonCreateInt(key, RyanJsonGetIntValue(pJson)); }
-		else if (RyanJsonIsDouble(pJson)) { newItem = RyanJsonCreateDouble(key, RyanJsonGetDoubleValue(pJson)); }
+		else
+		{
+			// 不可能出现另外一个条件了
+			RyanJsonCheckNeverNoAssert(RyanJsonIsDouble(pJson));
+			newItem = RyanJsonCreateDouble(key, RyanJsonGetDoubleValue(pJson));
+		}
 		break;
 
 	case RyanJsonTypeString: newItem = RyanJsonCreateString(key, RyanJsonGetStringValue(pJson)); break;
@@ -2191,7 +2200,7 @@ RyanJson_t RyanJsonDuplicate(RyanJson_t pJson)
 			item = RyanJsonDuplicate(temp);
 			RyanJsonCheckCode(NULL != item, { goto error__; });
 
-			// RyanJsonCheckAssert(RyanJsonTrue == RyanJsonInsert(newItem, UINT32_MAX, item));
+			// RyanJsonCheckNeverNoAssert(RyanJsonTrue == RyanJsonInsert(newItem, UINT32_MAX, item));
 
 			if (NULL != prev)
 			{
@@ -2223,7 +2232,7 @@ error__:
  * @brief 通过删除无效字符、注释等, 减少json文本大小
  *
  * @param text 文本指针
- * @param textLen 文本长度,使用int32_t是方式用户隐士转换不好发现bug
+ * @param textLen 文本长度,不使用uint32_t是方式用户传递的参数隐式转换不容易发现bug
  * @return uint32_t
  */
 uint32_t RyanJsonMinify(char *text, int32_t textLen)
@@ -2287,18 +2296,18 @@ uint32_t RyanJsonMinify(char *text, int32_t textLen)
  */
 RyanJsonBool_e RyanJsonCompare(RyanJson_t leftJson, RyanJson_t rightJson)
 {
-	if (NULL == leftJson || NULL == rightJson) { return RyanJsonFalse; }
+	RyanJsonCheckReturnFalse(NULL != leftJson && NULL != rightJson);
 
 	// 相同的对象相等
 	if (leftJson == rightJson) { return RyanJsonTrue; }
 
-	if (RyanJsonGetType(leftJson) != RyanJsonGetType(rightJson)) { return RyanJsonFalse; }
+	RyanJsonCheckReturnFalse(RyanJsonGetType(leftJson) == RyanJsonGetType(rightJson));
 
 	switch (RyanJsonGetType(leftJson))
 	{
 	case RyanJsonTypeNull: return RyanJsonTrue;
 
-	case RyanJsonTypeBool: return RyanJsonGetBoolValue(leftJson) == RyanJsonGetBoolValue(rightJson) ? RyanJsonTrue : RyanJsonFalse;
+	case RyanJsonTypeBool: return (RyanJsonGetBoolValue(leftJson) == RyanJsonGetBoolValue(rightJson)) ? RyanJsonTrue : RyanJsonFalse;
 
 	case RyanJsonTypeNumber: {
 
@@ -2320,13 +2329,13 @@ RyanJsonBool_e RyanJsonCompare(RyanJson_t leftJson, RyanJson_t rightJson)
 														  : RyanJsonFalse;
 
 	case RyanJsonTypeArray: {
-		if (RyanJsonGetSize(leftJson) != RyanJsonGetSize(rightJson)) { return RyanJsonFalse; }
+		RyanJsonCheckReturnFalse(RyanJsonGetSize(leftJson) == RyanJsonGetSize(rightJson));
 
 		RyanJson_t item;
 		uint32_t itemIndex = 0;
 		RyanJsonArrayForEach(leftJson, item)
 		{
-			if (RyanJsonTrue != RyanJsonCompare(item, RyanJsonGetObjectByIndex(rightJson, itemIndex))) { return RyanJsonFalse; }
+			RyanJsonCheckReturnFalse(RyanJsonTrue == RyanJsonCompare(item, RyanJsonGetObjectByIndex(rightJson, itemIndex)));
 			itemIndex++;
 		}
 
@@ -2334,15 +2343,13 @@ RyanJsonBool_e RyanJsonCompare(RyanJson_t leftJson, RyanJson_t rightJson)
 	}
 
 	case RyanJsonTypeObject: {
-		if (RyanJsonGetSize(leftJson) != RyanJsonGetSize(rightJson)) { return RyanJsonFalse; }
+		RyanJsonCheckReturnFalse(RyanJsonGetSize(leftJson) == RyanJsonGetSize(rightJson));
 
 		RyanJson_t item;
 		RyanJsonObjectForEach(leftJson, item)
 		{
-			if (RyanJsonTrue != RyanJsonCompare(item, RyanJsonGetObjectByKey(rightJson, RyanJsonGetKey(item))))
-			{
-				return RyanJsonFalse;
-			}
+			RyanJsonCheckReturnFalse(RyanJsonTrue ==
+						 RyanJsonCompare(item, RyanJsonGetObjectByKey(rightJson, RyanJsonGetKey(item))));
 		}
 
 		return RyanJsonTrue;

+ 4 - 2
RyanJson/RyanJson.h

@@ -22,10 +22,12 @@ extern "C" {
 
 #define RyanJsonCheckReturnFalse(EX) RyanJsonCheckCode(EX, return RyanJsonFalse;)
 #define RyanJsonCheckReturnNull(EX)  RyanJsonCheckCode(EX, return NULL;)
+
+// !没有使能assert时RyanJsonCheckAssert不执行的
 #ifdef RyanJsonEnableAssert
-#define RyanJsonCheckAssert(EX) RyanJsonCheckCode(EX, RyanJsonAssert(NULL && "RyanJsonCheckAssert");)
+#define RyanJsonCheckAssert(EX) RyanJsonCheckCode(EX, RyanJsonAssert(NULL &&#EX);)
 #else
-#define RyanJsonCheckAssert(EX) (void)(EX)
+#define RyanJsonCheckAssert(EX) ((void)0)
 #endif
 
 // Json 的最基础节点,所有 Json 元素都由该节点表示。

+ 8 - 12
RyanJson/RyanJsonUtils.c

@@ -115,12 +115,12 @@ RyanJson_t RyanJsonCreateStringArray(const char **strings, uint32_t count)
  */
 RyanJsonBool_e RyanJsonCompareOnlyKey(RyanJson_t leftJson, RyanJson_t rightJson)
 {
-	if (NULL == leftJson || NULL == rightJson) { return RyanJsonFalse; }
+	RyanJsonCheckReturnFalse(NULL != leftJson && NULL != rightJson);
 
 	// 相同的对象相等
 	if (leftJson == rightJson) { return RyanJsonTrue; }
 
-	if (RyanJsonGetType(leftJson) != RyanJsonGetType(rightJson)) { return RyanJsonFalse; }
+	RyanJsonCheckReturnFalse(RyanJsonGetType(leftJson) == RyanJsonGetType(rightJson));
 
 	switch (RyanJsonGetType(leftJson))
 	{
@@ -130,31 +130,27 @@ RyanJsonBool_e RyanJsonCompareOnlyKey(RyanJson_t leftJson, RyanJson_t rightJson)
 	case RyanJsonTypeString: return RyanJsonTrue;
 
 	case RyanJsonTypeArray: {
-		if (RyanJsonGetSize(leftJson) != RyanJsonGetSize(rightJson)) { return RyanJsonFalse; }
+		RyanJsonCheckReturnFalse(RyanJsonGetSize(leftJson) == RyanJsonGetSize(rightJson));
 
 		RyanJson_t item;
 		uint32_t itemIndex = 0;
 		RyanJsonArrayForEach(leftJson, item)
 		{
-			if (RyanJsonTrue != RyanJsonCompareOnlyKey(item, RyanJsonGetObjectByIndex(rightJson, itemIndex)))
-			{
-				return RyanJsonFalse;
-			}
+			RyanJsonCheckReturnFalse(RyanJsonTrue ==
+						 RyanJsonCompareOnlyKey(item, RyanJsonGetObjectByIndex(rightJson, itemIndex)));
 			itemIndex++;
 		}
 		return RyanJsonTrue;
 	}
 
 	case RyanJsonTypeObject: {
-		if (RyanJsonGetSize(leftJson) != RyanJsonGetSize(rightJson)) { return RyanJsonFalse; }
+		RyanJsonCheckReturnFalse(RyanJsonGetSize(leftJson) == RyanJsonGetSize(rightJson));
 
 		RyanJson_t item;
 		RyanJsonObjectForEach(leftJson, item)
 		{
-			if (RyanJsonTrue != RyanJsonCompareOnlyKey(item, RyanJsonGetObjectByKey(rightJson, RyanJsonGetKey(item))))
-			{
-				return RyanJsonFalse;
-			}
+			RyanJsonCheckReturnFalse(RyanJsonTrue ==
+						 RyanJsonCompareOnlyKey(item, RyanJsonGetObjectByKey(rightJson, RyanJsonGetKey(item))));
 		}
 		return RyanJsonTrue;
 	}

+ 52 - 8
test/fuzzer/RyanJsonFuzzer.c

@@ -11,6 +11,31 @@ static RyanJsonBool_e isEnableRandomMemFail = RyanJsonTrue;
 
 static RyanJsonBool_e RyanJsonFuzzerTestByParseAndPrint(RyanJson_t pJson, const char *data, uint32_t size)
 {
+	isEnableRandomMemFail = RyanJsonFalse;
+	RyanJson_t testItem = RyanJsonCreateObject();
+	RyanJson_t testItem2 = RyanJsonCreateObject();
+	RyanJsonSetType(testItem, 0);
+	RyanJsonSetType(testItem2, 0);
+	RyanJsonAssert(NULL == RyanJsonPrint(testItem, 100, RyanJsonFalse, NULL));
+	RyanJsonAssert(NULL == RyanJsonDuplicate(testItem));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonCompare(testItem, testItem2));
+
+	// 测试pJson类型错误情况
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(testItem, 0, RyanJsonCreateString("key", "true")));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(testItem2, UINT32_MAX, RyanJsonCreateString("key", "true")));
+
+	RyanJsonSetType(testItem, RyanJsonTypeObject);
+	RyanJsonSetType(testItem2, RyanJsonTypeObject);
+
+	// 测试pJson为obj,但是item没有key的情况
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(pJson, 0, RyanJsonCreateString(NULL, "true")));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(pJson, UINT32_MAX, RyanJsonCreateString(NULL, "true")));
+
+	RyanJsonAssert(RyanJsonTrue == RyanJsonInsert(pJson, 0, RyanJsonCreateString("key", "true")));
+	RyanJsonDelete(testItem);
+	RyanJsonDelete(testItem2);
+	isEnableRandomMemFail = RyanJsonTrue;
+
 	RyanJsonAssert(NULL == RyanJsonPrint(NULL, 100, RyanJsonFalse, NULL));
 	RyanJsonAssert(NULL == RyanJsonPrintPreallocated(NULL, NULL, 100, RyanJsonFalse, NULL));
 	RyanJsonAssert(NULL == RyanJsonPrintPreallocated(pJson, NULL, 100, RyanJsonFalse, NULL));
@@ -18,10 +43,13 @@ static RyanJsonBool_e RyanJsonFuzzerTestByParseAndPrint(RyanJson_t pJson, const
 	RyanJsonAssert(NULL == RyanJsonPrintPreallocated(pJson, (char *)data, 0, RyanJsonFalse, NULL));
 
 	uint32_t len = 0;
-	char *jsonStr =
-		RyanJsonPrint(pJson, size % 5 ? 100 : 0, size % 2 ? RyanJsonFalse : RyanJsonTrue, &len); // 以带格式方式将数据打印出来
+	char *jsonStr = RyanJsonPrint(pJson, size % 5 ? 100 : 0, size % 2 ? RyanJsonFalse : RyanJsonTrue, &len);
 	RyanJsonCheckReturnFalse(NULL != jsonStr && len > 0);
+
+	char *jsonStrCopy = RyanJsonPrint(pJson, size % 5 ? 100 : 0, size % 2 ? RyanJsonFalse : RyanJsonTrue, NULL); // 不传递len
+	RyanJsonAssert(0 == strncmp(jsonStr, jsonStrCopy, len));
 	RyanJsonFree(jsonStr);
+	RyanJsonFree(jsonStrCopy);
 
 	uint32_t bufLen = len * 3;
 	if (bufLen < size * 2) { bufLen = size * 2; }
@@ -121,6 +149,8 @@ static RyanJsonBool_e RyanJsonFuzzerTestByDup(RyanJson_t pJson)
 	{
 		// 测试size不相等
 		RyanJsonDelete(RyanJsonDetachByIndex(pJson, 0));
+		// 增加分支覆盖率
+		if (RyanJsonGetSize(pJson) > 2) { RyanJsonDelete(RyanJsonDetachByIndex(pJson, 1)); }
 
 		if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
 		{
@@ -186,7 +216,7 @@ static RyanJsonBool_e RyanJsonFuzzerTestByForEachChange(RyanJson_t pJson, uint32
 
 	if (RyanJsonIsKey(pJson))
 	{
-		char *key = malloc(strlen(RyanJsonGetKey(pJson)) + 1);
+		char *key = (char *)malloc(strlen(RyanJsonGetKey(pJson)) + 1);
 		if (key)
 		{
 			memcpy(key, RyanJsonGetKey(pJson), strlen(RyanJsonGetKey(pJson)));
@@ -216,13 +246,14 @@ static RyanJsonBool_e RyanJsonFuzzerTestByForEachChange(RyanJson_t pJson, uint32
 
 	if (RyanJsonIsString(pJson))
 	{
-		char *value = malloc(strlen(RyanJsonGetStringValue(pJson)) + 1);
+		char *value = (char *)malloc(strlen(RyanJsonGetStringValue(pJson)) + 1);
 		if (value)
 		{
 			memcpy(value, RyanJsonGetStringValue(pJson), strlen(RyanJsonGetStringValue(pJson)));
 			value[strlen(RyanJsonGetStringValue(pJson))] = 0;
 
 			RyanJsonChangeStringValue(pJson, "hello world");
+			RyanJsonChangeStringValue(pJson, "h");
 			RyanJsonChangeStringValue(pJson, value);
 
 			free(value);
@@ -250,6 +281,7 @@ static RyanJsonBool_e RyanJsonFuzzerTestByForEachGet2(RyanJson_t lastJson, RyanJ
 	RyanJsonAssert(0 == RyanJsonGetIntValue(NULL));
 	RyanJsonAssert(0 == RyanJsonGetDoubleValue(NULL));
 	RyanJsonAssert(NULL == RyanJsonGetObjectValue(NULL));
+	RyanJsonAssert(NULL == RyanJsonGetArrayValue(NULL));
 
 	RyanJsonAssert(NULL == RyanJsonGetObjectByKey(NULL, NULL));
 	RyanJsonAssert(NULL == RyanJsonGetObjectByKey(pJson, NULL));
@@ -282,6 +314,15 @@ static RyanJsonBool_e RyanJsonFuzzerTestByForEachGet2(RyanJson_t lastJson, RyanJ
 
 static RyanJsonBool_e RyanJsonFuzzerTestByForEachGet(RyanJson_t pJson, uint32_t size)
 {
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsKey(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsNull(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsBool(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsNumber(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsString(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsArray(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsObject(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsInt(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsDouble(NULL));
 
 	if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
 	{
@@ -327,9 +368,9 @@ static RyanJson_t RyanJsonFuzzerCreateRandomNode(RyanJson_t pJson)
 static RyanJsonBool_e RyanJsonFuzzerTestByForEachCreate(RyanJson_t pJson, uint32_t size)
 {
 	// RyanJsonInsert的特殊情况
-	RyanJsonCheckReturnFalse(RyanJsonFalse == RyanJsonInsert(NULL, UINT32_MAX, RyanJsonCreateString("key", "string")));
-	RyanJsonCheckReturnFalse(RyanJsonFalse == RyanJsonInsert(pJson, UINT32_MAX, NULL));
-	RyanJsonCheckReturnFalse(RyanJsonFalse == RyanJsonInsert(NULL, 0, NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(NULL, UINT32_MAX, RyanJsonCreateString("key", "string")));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(pJson, UINT32_MAX, NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(NULL, 0, NULL));
 
 	RyanJsonAssert(NULL == RyanJsonCreateString(NULL, NULL));
 	RyanJsonAssert(NULL == RyanJsonCreateString("NULL", NULL));
@@ -350,6 +391,9 @@ static RyanJsonBool_e RyanJsonFuzzerTestByForEachCreate(RyanJson_t pJson, uint32
 		RyanJsonAssert(RyanJsonFalse == RyanJsonChangeKey(pJson, "NULL"));
 	}
 
+	// 测试没有key但是有strValue的
+	if (!RyanJsonIsKey(pJson) && RyanJsonIsString(pJson)) { RyanJsonAssert(RyanJsonFalse == RyanJsonChangeKey(pJson, "NULL")); }
+
 	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeIntValue(NULL, 0));
 	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeDoubleValue(NULL, 0));
 
@@ -624,7 +668,7 @@ static RyanJsonBool_e RyanJsonFuzzerTestByForEachDelete(RyanJson_t pJson, uint32
 
 static RyanJsonBool_e RyanJsonFuzzerTestByMinify(const char *data, uint32_t size)
 {
-	char *buf = malloc(size + 100);
+	char *buf = (char *)malloc(size + 100);
 	memcpy(buf, data, size);
 	memset(buf + size, 0, 100);
 

+ 3 - 0
test/fuzzer/RyanJsonFuzzer.dict

@@ -25,16 +25,19 @@
 "\"status\""
 "\"error\""
 """
+"\"name"
 "\\"
 
 # 数字边界
 "0"
+"0000"
 "1"
 "-1"
 "1234567890"
 "3.14159"
 "1e10"
 "-1e-10"
+"-21474836470"
 "999999999999999999999999999"
 "-999999999999999999999999999"
 "-"