fuzzerModify.c 8.2 KB

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