fuzzerParse.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. #include "RyanJson.h"
  2. #include "RyanJsonFuzzer.h"
  3. /**
  4. * @brief 解析与打印测试
  5. *
  6. * 测试 RyanJson 的核心解析与打印路径。
  7. * 核心逻辑:
  8. * 错误注入测试:在内存分配失败场景下验证打印、复制与比较路径的健壮性。
  9. * 往返一致性验证:
  10. * - Parse(Print(Parse(Data))) 与 Parse(Data) 语义一致。
  11. * - 验证打印结果再次解析后,结构和内容保持稳定。
  12. * 预分配缓冲区打印测试:验证 PrintPreallocated 在不同容量下的行为。
  13. *
  14. * @param state Fuzzer 状态上下文
  15. * @param pJson 解析输入数据得到的初始 Json 对象
  16. * @param data 原始输入数据字符串
  17. * @param size 输入数据长度
  18. */
  19. RyanJsonBool_e RyanJsonFuzzerTestParse(RyanJson_t pJson, const char *data, uint32_t size)
  20. {
  21. // 一次性覆盖关键防御分支,避免依赖随机路径命中
  22. static RyanJsonBool_e coreBoundaryCovered = RyanJsonFalse;
  23. if (RyanJsonFalse == coreBoundaryCovered)
  24. {
  25. RyanJsonBool_e lastIsEnableMemFail = g_fuzzerState.isEnableMemFail;
  26. g_fuzzerState.isEnableMemFail = false;
  27. // 指数累积溢出防御
  28. assert(NULL == RyanJsonParse("1e2147483648"));
  29. assert(NULL == RyanJsonParse("1e-2147483648"));
  30. // 边界值:驱动 e_scale==INT32_MAX/10 且 digit<=INT32_MAX%10 的分支
  31. assert(NULL == RyanJsonParse("1e2147483647"));
  32. // 负指数边界会下溢到 0(有限数),属于可接受输入
  33. RyanJson_t negativeBoundary = RyanJsonParse("1e-2147483647");
  34. assert(NULL != negativeBoundary);
  35. RyanJsonDelete(negativeBoundary);
  36. assert(NULL == RyanJsonParse("{\"a\":1e2147483648}"));
  37. #if true == RyanJsonStrictObjectKeyCheck
  38. assert(NULL == RyanJsonParse("{\"dup\":1,\"dup\":2}"));
  39. #else
  40. {
  41. RyanJson_t dupObj = RyanJsonParse("{\"dup\":1,\"dup\":2}");
  42. assert(NULL != dupObj);
  43. RyanJsonDelete(dupObj);
  44. }
  45. #endif
  46. // 比较逻辑分支覆盖:
  47. // 根节点类型不一致,覆盖类型比较失败分支。
  48. // boolValue 不一致,覆盖布尔全量比较失败分支。
  49. // Int/Double 数值不一致,覆盖数值全量比较失败分支。
  50. // strValue 不一致,覆盖字符串全量比较失败分支。
  51. // 对象 key 乱序,覆盖对象下沉/同层 key 回退查找分支。
  52. // 对象缺 key,覆盖 rightChild == NULL 的失败分支。
  53. {
  54. RyanJson_t cmpInt = RyanJsonCreateInt(NULL, 1);
  55. RyanJson_t cmpString = RyanJsonCreateString(NULL, "1");
  56. assert(NULL != cmpInt && NULL != cmpString);
  57. assert(RyanJsonFalse == RyanJsonCompare(cmpInt, cmpString));
  58. assert(RyanJsonFalse == RyanJsonCompareOnlyKey(cmpInt, cmpString));
  59. RyanJsonDelete(cmpInt);
  60. RyanJsonDelete(cmpString);
  61. RyanJson_t cmpBoolTrue = RyanJsonCreateBool(NULL, RyanJsonTrue);
  62. RyanJson_t cmpBoolFalse = RyanJsonCreateBool(NULL, RyanJsonFalse);
  63. assert(NULL != cmpBoolTrue && NULL != cmpBoolFalse);
  64. assert(RyanJsonFalse == RyanJsonCompare(cmpBoolTrue, cmpBoolFalse));
  65. assert(RyanJsonTrue == RyanJsonCompareOnlyKey(cmpBoolTrue, cmpBoolFalse));
  66. RyanJsonDelete(cmpBoolTrue);
  67. RyanJsonDelete(cmpBoolFalse);
  68. RyanJson_t cmpIntLeft = RyanJsonCreateInt(NULL, 123);
  69. RyanJson_t cmpIntRight = RyanJsonCreateInt(NULL, 456);
  70. assert(NULL != cmpIntLeft && NULL != cmpIntRight);
  71. assert(RyanJsonFalse == RyanJsonCompare(cmpIntLeft, cmpIntRight));
  72. assert(RyanJsonTrue == RyanJsonCompareOnlyKey(cmpIntLeft, cmpIntRight));
  73. RyanJsonDelete(cmpIntLeft);
  74. RyanJsonDelete(cmpIntRight);
  75. RyanJson_t cmpDoubleLeft = RyanJsonCreateDouble(NULL, 1.0);
  76. RyanJson_t cmpDoubleRight = RyanJsonCreateDouble(NULL, 2.0);
  77. assert(NULL != cmpDoubleLeft && NULL != cmpDoubleRight);
  78. assert(RyanJsonFalse == RyanJsonCompare(cmpDoubleLeft, cmpDoubleRight));
  79. assert(RyanJsonTrue == RyanJsonCompareOnlyKey(cmpDoubleLeft, cmpDoubleRight));
  80. RyanJsonDelete(cmpDoubleLeft);
  81. RyanJsonDelete(cmpDoubleRight);
  82. RyanJson_t cmpStrLeft = RyanJsonCreateString(NULL, "alpha");
  83. RyanJson_t cmpStrRight = RyanJsonCreateString(NULL, "beta");
  84. assert(NULL != cmpStrLeft && NULL != cmpStrRight);
  85. assert(RyanJsonFalse == RyanJsonCompare(cmpStrLeft, cmpStrRight));
  86. assert(RyanJsonTrue == RyanJsonCompareOnlyKey(cmpStrLeft, cmpStrRight));
  87. RyanJsonDelete(cmpStrLeft);
  88. RyanJsonDelete(cmpStrRight);
  89. RyanJson_t objLeft = RyanJsonCreateObject();
  90. RyanJson_t objRightUnordered = RyanJsonCreateObject();
  91. assert(NULL != objLeft && NULL != objRightUnordered);
  92. assert(RyanJsonTrue == RyanJsonAddIntToObject(objLeft, "a", 1));
  93. assert(RyanJsonTrue == RyanJsonAddIntToObject(objLeft, "b", 2));
  94. assert(RyanJsonTrue == RyanJsonAddIntToObject(objLeft, "c", 3));
  95. assert(RyanJsonTrue == RyanJsonAddIntToObject(objRightUnordered, "b", 2));
  96. assert(RyanJsonTrue == RyanJsonAddIntToObject(objRightUnordered, "a", 1));
  97. assert(RyanJsonTrue == RyanJsonAddIntToObject(objRightUnordered, "c", 3));
  98. assert(RyanJsonTrue == RyanJsonCompare(objLeft, objRightUnordered));
  99. assert(RyanJsonTrue == RyanJsonCompareOnlyKey(objLeft, objRightUnordered));
  100. RyanJsonDelete(objLeft);
  101. RyanJsonDelete(objRightUnordered);
  102. RyanJson_t objNeedKey = RyanJsonCreateObject();
  103. RyanJson_t objMissKey = RyanJsonCreateObject();
  104. assert(NULL != objNeedKey && NULL != objMissKey);
  105. assert(RyanJsonTrue == RyanJsonAddIntToObject(objNeedKey, "a", 1));
  106. assert(RyanJsonTrue == RyanJsonAddIntToObject(objMissKey, "b", 1));
  107. assert(RyanJsonFalse == RyanJsonCompare(objNeedKey, objMissKey));
  108. assert(RyanJsonFalse == RyanJsonCompareOnlyKey(objNeedKey, objMissKey));
  109. RyanJsonDelete(objNeedKey);
  110. RyanJsonDelete(objMissKey);
  111. // 命中同层快路径中 rightCandidate == NULL 的分支:
  112. // 左侧首 key=a,右侧将 a 放到最后;第一次下沉后 rightCurrent 位于尾节点。
  113. // 比较 leftNext 时 rightCandidate 为 NULL,必须走按 key 回退查找。
  114. RyanJson_t objLastHitLeft = RyanJsonCreateObject();
  115. RyanJson_t objLastHitRight = RyanJsonCreateObject();
  116. assert(NULL != objLastHitLeft && NULL != objLastHitRight);
  117. assert(RyanJsonTrue == RyanJsonAddIntToObject(objLastHitLeft, "a", 1));
  118. assert(RyanJsonTrue == RyanJsonAddIntToObject(objLastHitLeft, "b", 2));
  119. assert(RyanJsonTrue == RyanJsonAddIntToObject(objLastHitLeft, "c", 3));
  120. assert(RyanJsonTrue == RyanJsonAddIntToObject(objLastHitRight, "b", 2));
  121. assert(RyanJsonTrue == RyanJsonAddIntToObject(objLastHitRight, "c", 3));
  122. assert(RyanJsonTrue == RyanJsonAddIntToObject(objLastHitRight, "a", 1));
  123. assert(RyanJsonTrue == RyanJsonCompare(objLastHitLeft, objLastHitRight));
  124. assert(RyanJsonTrue == RyanJsonCompareOnlyKey(objLastHitLeft, objLastHitRight));
  125. RyanJsonDelete(objLastHitLeft);
  126. RyanJsonDelete(objLastHitRight);
  127. // 命中同层回退查找失败(rightNext == NULL)分支:
  128. // 首 key 相同、后续 key 不同且 size 相同,失败点落在同层阶段而非下沉阶段。
  129. RyanJson_t objPrefixLeft = RyanJsonCreateObject();
  130. RyanJson_t objPrefixRight = RyanJsonCreateObject();
  131. assert(NULL != objPrefixLeft && NULL != objPrefixRight);
  132. assert(RyanJsonTrue == RyanJsonAddIntToObject(objPrefixLeft, "a", 1));
  133. assert(RyanJsonTrue == RyanJsonAddIntToObject(objPrefixLeft, "b", 2));
  134. assert(RyanJsonTrue == RyanJsonAddIntToObject(objPrefixRight, "a", 1));
  135. assert(RyanJsonTrue == RyanJsonAddIntToObject(objPrefixRight, "c", 2));
  136. assert(RyanJsonFalse == RyanJsonCompare(objPrefixLeft, objPrefixRight));
  137. assert(RyanJsonFalse == RyanJsonCompareOnlyKey(objPrefixLeft, objPrefixRight));
  138. RyanJsonDelete(objPrefixLeft);
  139. RyanJsonDelete(objPrefixRight);
  140. // 容器内数值子类型:全量比较要求一致,仅比较 key 时允许 int/double 混用。
  141. RyanJson_t numberSubtypeLeft = RyanJsonParse("{\"n\":1,\"arr\":[1,2.0],\"obj\":{\"x\":3,\"y\":4.0}}");
  142. RyanJson_t numberSubtypeRight = RyanJsonParse("{\"obj\":{\"y\":4,\"x\":3.0},\"arr\":[1.0,2],\"n\":1.0}");
  143. assert(NULL != numberSubtypeLeft && NULL != numberSubtypeRight);
  144. assert(RyanJsonFalse == RyanJsonCompare(numberSubtypeLeft, numberSubtypeRight));
  145. assert(RyanJsonTrue == RyanJsonCompareOnlyKey(numberSubtypeLeft, numberSubtypeRight));
  146. RyanJsonDelete(numberSubtypeLeft);
  147. RyanJsonDelete(numberSubtypeRight);
  148. }
  149. // int32 打印边界:11(不含 \0 空间)失败,12(含 \0 空间)成功
  150. RyanJson_t intItem = RyanJsonCreateInt(NULL, INT32_MIN);
  151. assert(NULL != intItem);
  152. char tooSmall[11] = {0};
  153. assert(NULL == RyanJsonPrintPreallocated(intItem, tooSmall, sizeof(tooSmall), RyanJsonFalse, NULL));
  154. char exactFit[12] = {0};
  155. char *exactOut = RyanJsonPrintPreallocated(intItem, exactFit, sizeof(exactFit), RyanJsonFalse, NULL);
  156. assert(NULL != exactOut);
  157. assert(0 == strcmp(exactOut, "-2147483648"));
  158. RyanJsonDelete(intItem);
  159. // 预分配“刚好够用”的成功路径(非数值节点)
  160. {
  161. RyanJson_t strObj = RyanJsonCreateObject();
  162. assert(NULL != strObj);
  163. assert(RyanJsonTrue == RyanJsonAddStringToObject(strObj, "k", "v"));
  164. uint32_t expectedLen = 0;
  165. char *expected = RyanJsonPrint(strObj, 0, RyanJsonFalse, &expectedLen);
  166. assert(NULL != expected);
  167. char exactBuf[16] = {0};
  168. assert(expectedLen + 1U <= sizeof(exactBuf));
  169. char *exactStr = RyanJsonPrintPreallocated(strObj, exactBuf, expectedLen + 1U, RyanJsonFalse, NULL);
  170. assert(NULL != exactStr);
  171. assert(0 == strcmp(expected, exactStr));
  172. RyanJsonFree(expected);
  173. RyanJsonDelete(strObj);
  174. }
  175. g_fuzzerState.isEnableMemFail = lastIsEnableMemFail;
  176. coreBoundaryCovered = RyanJsonTrue;
  177. }
  178. if (RyanJsonFuzzerShouldFail(100))
  179. {
  180. assert(1 == RyanJsonInternalCalcLenBytes(UINT8_MAX - 1));
  181. assert(1 == RyanJsonInternalCalcLenBytes(UINT8_MAX));
  182. assert(2 == RyanJsonInternalCalcLenBytes((uint32_t)UINT8_MAX + 1U));
  183. assert(2 == RyanJsonInternalCalcLenBytes(UINT16_MAX));
  184. assert(3 == RyanJsonInternalCalcLenBytes(UINT32_MAX - 1));
  185. assert(1 == RyanJsonInternalDecodeKeyLenField(0x01));
  186. assert(2 == RyanJsonInternalDecodeKeyLenField(0x02));
  187. assert(4 == RyanJsonInternalDecodeKeyLenField(0x03));
  188. g_fuzzerState.isEnableMemFail = false; // 临时禁用内存失败模拟,便于构造测试对象
  189. RyanJson_t objItem = RyanJsonCreateObject();
  190. RyanJson_t objItem2 = RyanJsonCreateObject();
  191. // 故意设置错误的类型标志,测试鲁棒性
  192. RyanJsonSetType(objItem, 0);
  193. RyanJsonSetType(objItem2, 0);
  194. // 验证异常状态下的 API 行为
  195. assert(NULL == RyanJsonPrint(objItem, 100, RyanJsonFalse, NULL));
  196. assert(NULL == RyanJsonDuplicate(objItem));
  197. assert(RyanJsonFalse == RyanJsonCompare(objItem, objItem2));
  198. assert(RyanJsonFalse == RyanJsonCompareOnlyKey(objItem, objItem2));
  199. // 测试 Insert 类型检查
  200. assert(RyanJsonFalse == RyanJsonInsert(objItem, 0, RyanJsonCreateString("key", "true")));
  201. assert(RyanJsonFalse == RyanJsonInsert(objItem2, UINT32_MAX, RyanJsonCreateString("key", "true")));
  202. // 恢复正确类型
  203. RyanJsonSetType(objItem, RyanJsonTypeObject);
  204. RyanJsonSetType(objItem2, RyanJsonTypeObject);
  205. // 测试 Insert 异常参数
  206. if (RyanJsonIsObject(pJson))
  207. {
  208. assert(RyanJsonFalse == RyanJsonInsert(pJson, 0, RyanJsonCreateString(NULL, "true"))); // 缺少 key
  209. assert(RyanJsonFalse == RyanJsonInsert(pJson, UINT32_MAX, RyanJsonCreateString(NULL, "true")));
  210. }
  211. // 正常插入尝试
  212. if (RyanJsonIsArray(pJson)) { assert(RyanJsonTrue == RyanJsonInsert(pJson, 0, RyanJsonCreateString(NULL, "true"))); }
  213. else if (RyanJsonIsObject(pJson))
  214. {
  215. // 对象 key 需唯一:为插入构造一个未使用的 key
  216. RyanJsonBool_e foundUniqueKey = RyanJsonFalse;
  217. char keyBuf[32];
  218. for (uint32_t i = 0; i < 128; i++)
  219. {
  220. if (0 == i) { RyanJsonSnprintf(keyBuf, sizeof(keyBuf), "key"); }
  221. else
  222. {
  223. RyanJsonSnprintf(keyBuf, sizeof(keyBuf), "__fuzz_key_%u__", (unsigned)i);
  224. }
  225. if (RyanJsonFalse == RyanJsonHasObjectByKey(pJson, keyBuf))
  226. {
  227. foundUniqueKey = RyanJsonTrue;
  228. break;
  229. }
  230. }
  231. if (foundUniqueKey)
  232. {
  233. RyanJson_t insertItem = RyanJsonCreateString(keyBuf, "true");
  234. assert(NULL != insertItem);
  235. assert(RyanJsonTrue == RyanJsonInsert(pJson, 0, insertItem));
  236. }
  237. }
  238. RyanJsonDelete(objItem);
  239. RyanJsonDelete(objItem2);
  240. g_fuzzerState.isEnableMemFail = true; // 重新启用内存失败模拟
  241. // 验证 Print 系列函数的空指针处理
  242. assert(NULL == RyanJsonPrint(NULL, 100, RyanJsonFalse, NULL));
  243. assert(NULL == RyanJsonPrintWithStyle(pJson, 100, NULL, NULL));
  244. assert(NULL == RyanJsonPrintPreallocated(NULL, NULL, 100, RyanJsonFalse, NULL));
  245. assert(NULL == RyanJsonPrintPreallocated(pJson, NULL, 100, RyanJsonFalse, NULL));
  246. assert(NULL == RyanJsonPrintPreallocated(NULL, (char *)data, 100, RyanJsonFalse, NULL));
  247. assert(NULL == RyanJsonPrintPreallocated(pJson, (char *)data, 0, RyanJsonFalse, NULL));
  248. assert(NULL == RyanJsonPrintPreallocatedWithStyle(pJson, (char *)data, 100, NULL, NULL));
  249. assert(NULL == RyanJsonParse(NULL));
  250. // 特殊 doubleValue 打印(NaN / Infinity 输出为 null)
  251. {
  252. RyanJson_t specialObj = RyanJsonCreateObject();
  253. if (specialObj)
  254. {
  255. g_fuzzerState.isEnableMemFail = false;
  256. RyanJsonAddDoubleToObject(specialObj, "inf", INFINITY);
  257. RyanJsonAddDoubleToObject(specialObj, "ninf", -INFINITY);
  258. RyanJsonAddDoubleToObject(specialObj, "nan", NAN);
  259. g_fuzzerState.isEnableMemFail = true;
  260. uint32_t specialLen = 0;
  261. char *specialStr = RyanJsonPrint(specialObj, 100, RyanJsonFalse, &specialLen);
  262. if (specialStr)
  263. {
  264. assert(NULL != strstr(specialStr, "\"inf\":null"));
  265. assert(NULL != strstr(specialStr, "\"ninf\":null"));
  266. assert(NULL != strstr(specialStr, "\"nan\":null"));
  267. RyanJsonFree(specialStr);
  268. }
  269. RyanJsonDelete(specialObj);
  270. }
  271. }
  272. // 数值溢出路径覆盖(int/double)
  273. {
  274. g_fuzzerState.isEnableMemFail = false;
  275. uint32_t hugeIntLen = 600;
  276. uint32_t hugeFracLen = 1000;
  277. char *hugeBuf = (char *)malloc(hugeFracLen);
  278. if (hugeBuf)
  279. {
  280. memset(hugeBuf, '9', (size_t)(hugeIntLen - 1));
  281. hugeBuf[0] = '1';
  282. hugeBuf[hugeIntLen - 1] = '\0';
  283. RyanJson_t hugeIntJson = RyanJsonParse(hugeBuf);
  284. assert(NULL == hugeIntJson);
  285. if (hugeIntJson) { RyanJsonDelete(hugeIntJson); }
  286. hugeBuf[0] = '0';
  287. hugeBuf[1] = '.';
  288. memset(hugeBuf + 2, '9', (size_t)(hugeFracLen - 3));
  289. hugeBuf[hugeFracLen - 1] = '\0';
  290. RyanJson_t hugeFracJson = RyanJsonParse(hugeBuf);
  291. assert(NULL == hugeFracJson);
  292. if (hugeFracJson) { RyanJsonDelete(hugeFracJson); }
  293. free(hugeBuf);
  294. g_fuzzerState.isEnableMemFail = true;
  295. }
  296. }
  297. }
  298. RyanJsonBool isPrintFormat = size % 2 ? RyanJsonFalse : RyanJsonTrue;
  299. if (size > 1024) { isPrintFormat = RyanJsonFalse; }
  300. if (size > 512) { return RyanJsonTrue; }
  301. // 序列化一致性校验
  302. uint32_t len = 0;
  303. // 随机选择是否格式化,增加覆盖面
  304. char *jsonStr = RyanJsonPrint(pJson, isPrintFormat ? size : 0, isPrintFormat, &len);
  305. RyanJsonCheckReturnFalse(NULL != jsonStr);
  306. // 验证不传长度指针的情况
  307. g_fuzzerState.isEnableMemFail = false;
  308. char *jsonStrCopy = RyanJsonPrint(pJson, isPrintFormat ? size : 0, isPrintFormat, NULL);
  309. g_fuzzerState.isEnableMemFail = true;
  310. assert(0 == strncmp(jsonStr, jsonStrCopy, len));
  311. RyanJsonFree(jsonStrCopy);
  312. RyanJsonFree(jsonStr);
  313. // 预分配缓冲区打印测试
  314. // 验证在有限缓冲区、刚好够用缓冲区等情况下的打印行为
  315. uint32_t bufLen = len * 1.2;
  316. if (bufLen < size * 1.5) { bufLen = size * 1.5; }
  317. if (bufLen < 1024) { bufLen = 1024; }
  318. char *buf = (char *)malloc((size_t)bufLen);
  319. if (!buf) { return RyanJsonFalse; }
  320. {
  321. uint32_t len2 = 0;
  322. // RyanJson 内部可能返回失败
  323. g_fuzzerState.isEnableMemFail = false;
  324. char *jsonStr2 = RyanJsonPrintPreallocated(pJson, buf, bufLen, isPrintFormat, &len2);
  325. g_fuzzerState.isEnableMemFail = true;
  326. assert(NULL != jsonStr2);
  327. assert(len == len2);
  328. // assert(0 == strncmp(jsonStr, jsonStr2, len));
  329. }
  330. // 解析原始数据测试
  331. // 注意:输入数据不一定以 \0 结尾,因此需要手动补终止符
  332. memcpy(buf, data, (size_t)size);
  333. buf[size] = 0;
  334. RyanJson_t jsonRoot = RyanJsonParse(buf);
  335. RyanJsonCheckCode(NULL != jsonRoot, {
  336. free(buf);
  337. return RyanJsonFalse;
  338. });
  339. // 二次序列化校验
  340. // 这里验证 parsedRoot 可被稳定打印。
  341. // 仅当原始输入是合法 Json 且格式一致时,字符串内容才可能完全一致。
  342. {
  343. uint32_t len3 = 0;
  344. // 使用与第一次打印相同的参数
  345. char *jsonStr3 = RyanJsonPrint(jsonRoot, 100, size % 2 ? RyanJsonFalse : RyanJsonTrue, &len3);
  346. // 这里只校验非空,因为原始 data 可能包含冗余空白或格式差异,
  347. // 导致 Parse 后再 Print 与原始 data 不完全一致是正常现象。
  348. // 这里主要确认解析结果可被稳定打印。
  349. RyanJsonCheckCode(NULL != jsonStr3, {
  350. free(buf);
  351. if (jsonStr3) { RyanJsonFree(jsonStr3); }
  352. RyanJsonDelete(jsonRoot);
  353. return RyanJsonFalse;
  354. });
  355. RyanJsonFree(jsonStr3);
  356. }
  357. // 边界测试:缓冲区极小的情况
  358. {
  359. RyanJsonPrintPreallocated(jsonRoot, buf, bufLen / 15, RyanJsonTrue, NULL);
  360. }
  361. free(buf);
  362. RyanJsonDelete(jsonRoot);
  363. return RyanJsonTrue;
  364. }