fuzzerModify.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. #include "RyanJson.h"
  2. #include "RyanJsonFuzzer.h"
  3. /**
  4. * @brief 修改与访问测试
  5. *
  6. * 测试 RyanJson 的节点修改能力(Change 值/key)以及数据访问安全性。
  7. * 覆盖场景:
  8. * 异常参数修改:测试空指针、类型不匹配时的修改行为。
  9. * 递归修改:遍历 Json 树,随机修改子节点的值或 key。
  10. * 类型安全访问:测试类型不匹配时调用 Get 接口的安全性(例如对 Int 调用 GetString)。
  11. * 访问正确性验证:验证 Get 接口返回值与 Set 结果一致。
  12. *
  13. * @param state Fuzzer 状态上下文
  14. * @param pJson 当前正在操作的 Json 节点
  15. * @param size 输入数据大小
  16. */
  17. RyanJsonBool_e RyanJsonFuzzerTestModify(RyanJson_t pJson, uint32_t size)
  18. {
  19. // 一次性覆盖 Change 参数/类型防御分支,并验证失败不改值
  20. static RyanJsonBool_e changeGuardCovered = RyanJsonFalse;
  21. if (RyanJsonFalse == changeGuardCovered)
  22. {
  23. RyanJsonBool_e lastIsEnableMemFail = g_fuzzerState.isEnableMemFail;
  24. g_fuzzerState.isEnableMemFail = false;
  25. RyanJson_t intNode = RyanJsonCreateInt(NULL, 123);
  26. RyanJson_t doubleNode = RyanJsonCreateDouble(NULL, 1.25);
  27. RyanJson_t boolNode = RyanJsonCreateBool("flag", RyanJsonTrue);
  28. RyanJson_t strNode = RyanJsonCreateString("k", "v");
  29. if (intNode)
  30. {
  31. assert(RyanJsonFalse == RyanJsonChangeDoubleValue(intNode, 9.9));
  32. assert(123 == RyanJsonGetIntValue(intNode));
  33. }
  34. if (doubleNode)
  35. {
  36. assert(RyanJsonFalse == RyanJsonChangeIntValue(doubleNode, 7));
  37. assert(RyanJsonTrue == RyanJsonCompareDouble(1.25, RyanJsonGetDoubleValue(doubleNode)));
  38. }
  39. if (boolNode)
  40. {
  41. assert(RyanJsonFalse == RyanJsonChangeIntValue(boolNode, 1));
  42. assert(RyanJsonTrue == RyanJsonGetBoolValue(boolNode));
  43. assert(RyanJsonTrue == RyanJsonChangeKey(boolNode, "flag2"));
  44. assert(0 == strcmp(RyanJsonGetKey(boolNode), "flag2"));
  45. }
  46. if (strNode)
  47. {
  48. // 命中 RyanJsonChangeStringValue 中 RyanJsonIsKey(pJson)==true 的分支
  49. assert(RyanJsonTrue == RyanJsonChangeStringValue(strNode, "v2"));
  50. assert(0 == strcmp(RyanJsonGetStringValue(strNode), "v2"));
  51. assert(0 == strcmp(RyanJsonGetKey(strNode), "k"));
  52. assert(RyanJsonFalse == RyanJsonChangeBoolValue(strNode, RyanJsonFalse));
  53. assert(0 == strcmp(RyanJsonGetStringValue(strNode), "v2"));
  54. assert(RyanJsonFalse == RyanJsonChangeKey(strNode, NULL));
  55. assert(0 == strcmp(RyanJsonGetKey(strNode), "k"));
  56. }
  57. RyanJsonDelete(intNode);
  58. RyanJsonDelete(doubleNode);
  59. RyanJsonDelete(boolNode);
  60. RyanJsonDelete(strNode);
  61. g_fuzzerState.isEnableMemFail = lastIsEnableMemFail;
  62. changeGuardCovered = RyanJsonTrue;
  63. }
  64. // 修改 key 测试
  65. if (RyanJsonIsKey(pJson))
  66. {
  67. const char *oldKey = RyanJsonGetKey(pJson);
  68. if (oldKey)
  69. {
  70. // 备份原始 key
  71. size_t keyLen = strlen(oldKey);
  72. char *backupKey = (char *)malloc(keyLen + 1);
  73. if (backupKey)
  74. {
  75. memcpy(backupKey, oldKey, keyLen);
  76. backupKey[keyLen] = 0;
  77. // 修改为临时 key
  78. if (RyanJsonTrue == RyanJsonChangeKey(pJson, "temp_modified_key"))
  79. {
  80. fuzzTestWithMemFail({ assert(0 == strcmp(RyanJsonGetKey(pJson), "temp_modified_key")); });
  81. }
  82. // 恢复原始 key(确保结构一致,避免影响后续测试)
  83. if (RyanJsonTrue == RyanJsonChangeKey(pJson, backupKey))
  84. {
  85. fuzzTestWithMemFail({ assert(0 == strcmp(RyanJsonGetKey(pJson), backupKey)); });
  86. }
  87. free(backupKey);
  88. }
  89. }
  90. }
  91. // 布尔节点
  92. if (RyanJsonIsBool(pJson))
  93. {
  94. RyanJsonBool_e oldBool = RyanJsonGetBoolValue(pJson);
  95. if (RyanJsonTrue == RyanJsonChangeBoolValue(pJson, !oldBool))
  96. {
  97. fuzzTestWithMemFail({ assert(RyanJsonGetBoolValue(pJson) == !oldBool); });
  98. }
  99. if (RyanJsonTrue == RyanJsonChangeBoolValue(pJson, oldBool)) // 恢复
  100. {
  101. fuzzTestWithMemFail({ assert(RyanJsonGetBoolValue(pJson) == oldBool); });
  102. }
  103. }
  104. // 数值节点(Int/Double)
  105. if (RyanJsonIsNumber(pJson))
  106. {
  107. if (RyanJsonIsInt(pJson))
  108. {
  109. int32_t oldInt = RyanJsonGetIntValue(pJson);
  110. if (RyanJsonTrue == RyanJsonChangeIntValue(pJson, (int32_t)size))
  111. {
  112. fuzzTestWithMemFail({ assert(RyanJsonGetIntValue(pJson) == (int32_t)size); });
  113. }
  114. if (RyanJsonTrue == RyanJsonChangeIntValue(pJson, oldInt)) // 恢复
  115. {
  116. fuzzTestWithMemFail({ assert(RyanJsonGetIntValue(pJson) == oldInt); });
  117. }
  118. }
  119. if (RyanJsonIsDouble(pJson))
  120. {
  121. double oldDouble = RyanJsonGetDoubleValue(pJson);
  122. if (RyanJsonTrue == RyanJsonChangeDoubleValue(pJson, size * 1.123456789))
  123. {
  124. fuzzTestWithMemFail({ assert(RyanJsonCompareDouble(RyanJsonGetDoubleValue(pJson), size * 1.123456789)); });
  125. }
  126. if (RyanJsonTrue == RyanJsonChangeDoubleValue(pJson, oldDouble)) // 恢复
  127. {
  128. fuzzTestWithMemFail({ assert(RyanJsonCompareDouble(RyanJsonGetDoubleValue(pJson), oldDouble)); });
  129. }
  130. }
  131. }
  132. // 字符串节点
  133. if (RyanJsonIsString(pJson))
  134. {
  135. const char *oldStr = RyanJsonGetStringValue(pJson);
  136. if (oldStr)
  137. {
  138. size_t strLen = strlen(oldStr);
  139. char *backupStr = (char *)malloc(strLen + 1);
  140. if (backupStr)
  141. {
  142. memcpy(backupStr, oldStr, strLen);
  143. backupStr[strLen] = 0;
  144. if (RyanJsonTrue == RyanJsonChangeStringValue(pJson, "modified_string_value"))
  145. {
  146. fuzzTestWithMemFail(
  147. { assert(0 == strcmp(RyanJsonGetStringValue(pJson), "modified_string_value")); });
  148. }
  149. if (RyanJsonTrue == RyanJsonChangeStringValue(pJson, "short"))
  150. {
  151. fuzzTestWithMemFail({ assert(0 == strcmp(RyanJsonGetStringValue(pJson), "short")); });
  152. }
  153. if (RyanJsonTrue == RyanJsonChangeStringValue(pJson, backupStr)) // 恢复
  154. {
  155. fuzzTestWithMemFail({ assert(0 == strcmp(RyanJsonGetStringValue(pJson), backupStr)); });
  156. }
  157. free(backupStr);
  158. }
  159. }
  160. }
  161. // 递归遍历
  162. if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
  163. {
  164. RyanJson_t item;
  165. RyanJsonArrayForEach(pJson, item)
  166. {
  167. RyanJsonCheckReturnFalse(RyanJsonTrue == RyanJsonFuzzerTestModify(item, size));
  168. }
  169. }
  170. return RyanJsonTrue;
  171. }
  172. RyanJsonBool_e RyanJsonFuzzerVerifyGet(RyanJson_t parent, RyanJson_t current, uint32_t index, uint32_t size)
  173. {
  174. (void)size; // 未使用
  175. RyanJsonIsNull(current);
  176. // Get 接口前置条件:调用方需保证 pJson 非 NULL 且类型匹配。
  177. // 这里只保留可明确约定返回值的 GetObjectByKey 参数防御验证。
  178. // 验证 GetObjectByKey 异常参数
  179. assert(NULL == RyanJsonGetObjectByKey(NULL, NULL));
  180. assert(NULL == RyanJsonGetObjectByKey(current, NULL));
  181. assert(NULL == RyanJsonGetObjectByKey(NULL, "NULL"));
  182. assert(NULL == RyanJsonGetObjectToKey(NULL, NULL));
  183. assert(NULL == RyanJsonGetObjectToKey(current, NULL));
  184. assert(NULL == RyanJsonGetObjectToKey(NULL, "NULL"));
  185. // 验证 GetObjectByIndex 异常参数
  186. assert(NULL == RyanJsonGetObjectByIndex(NULL, 10));
  187. // 验证错误类型调用
  188. if (!RyanJsonIsObject(current)) { assert(NULL == RyanJsonGetObjectByKey(current, "NULL")); }
  189. // 验证 GetObjectByIndex 错误类型调用
  190. if (!RyanJsonIsArray(current) && !RyanJsonIsObject(current)) { assert(NULL == RyanJsonGetObjectByIndex(current, 0)); }
  191. // 验证父子关系查找
  192. // 确认当前节点 current 可以通过 parent + key/index 找回
  193. if (RyanJsonIsKey(current))
  194. {
  195. // 如果是 key 类型,应能通过 parent + key 找回(或找回其对应值)
  196. // 注意:RyanJsonGetObjectByKey 通常返回值节点,而非 key 节点本身
  197. // 但在 RyanJson 实现中,key 节点与 value 节点关系较紧密,返回语义由实现细节决定
  198. // 这里只调用 API 增加覆盖率,不做强一致性断言,因为实现细节可能复杂
  199. RyanJsonGetObjectToKey(parent, RyanJsonGetKey(current));
  200. }
  201. else
  202. {
  203. // 否则尝试通过 index 访问
  204. RyanJsonGetObjectToIndex(parent, index);
  205. }
  206. // 递归验证
  207. if (RyanJsonIsArray(current) || RyanJsonIsObject(current))
  208. {
  209. RyanJson_t item;
  210. // 这里的 index 是相对于 current 的子索引
  211. uint32_t childIndex = 0;
  212. RyanJsonObjectForEach(current, item)
  213. {
  214. RyanJsonFuzzerVerifyGet(current, item, childIndex, size);
  215. childIndex++;
  216. }
  217. }
  218. return RyanJsonTrue;
  219. }
  220. RyanJsonBool_e RyanJsonFuzzerTestGet(RyanJson_t pJson, uint32_t size)
  221. {
  222. // 全局异常测试
  223. assert(RyanJsonFalse == RyanJsonIsKey(NULL));
  224. assert(RyanJsonFalse == RyanJsonIsNull(NULL));
  225. assert(RyanJsonFalse == RyanJsonIsBool(NULL));
  226. assert(RyanJsonFalse == RyanJsonIsNumber(NULL));
  227. assert(RyanJsonFalse == RyanJsonIsString(NULL));
  228. assert(RyanJsonFalse == RyanJsonIsArray(NULL));
  229. assert(RyanJsonFalse == RyanJsonIsObject(NULL));
  230. assert(RyanJsonFalse == RyanJsonIsInt(NULL));
  231. assert(RyanJsonFalse == RyanJsonIsDouble(NULL));
  232. // 遍历测试
  233. if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
  234. {
  235. RyanJson_t item;
  236. uint32_t index = 0;
  237. RyanJsonObjectForEach(pJson, item)
  238. {
  239. RyanJsonFuzzerVerifyGet(pJson, item, index, size);
  240. index++;
  241. }
  242. }
  243. return RyanJsonTrue;
  244. }