AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <stdint.h>6 7/* Wrapper is provided in the module for static function */8extern u32 test_jsonbValidityCheck(const JsonParse *pParse, u32 i, u32 iEnd, u32 iDepth);9 10void setUp(void) {11 /* no-op */12}13void tearDown(void) {14 /* no-op */15}16 17/* Helpers to build JSONB elements */18static inline u8 hdr_sz1(u8 type, u8 sz){19 return (u8)((sz<<4) | (type&0x0f));20}21static inline u8 hdr_sel(u8 type, u8 sel){ /* sel = 12,13,14 */22 return (u8)((sel<<4) | (type&0x0f));23}24static u32 runCheck(const u8 *buf, u32 n, u32 depth){25 JsonParse p;26 memset(&p, 0, sizeof(p));27 p.aBlob = (u8*)buf;28 p.nBlob = n;29 p.delta = 0;30 return test_jsonbValidityCheck(&p, 0, n, depth);31}32 33/* -------- Tests -------- */34 35void test_jsonbValidityCheck_valid_null_true_false(void){36 /* NULL valid */37 {38 u8 b[] = { hdr_sz1(JSONB_NULL, 0) };39 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));40 }41 /* TRUE with non-zero payload => error at offset 1 (i+1) */42 {43 u8 b[] = { hdr_sz1(JSONB_TRUE, 1), 'X' };44 TEST_ASSERT_EQUAL_UINT32(1, runCheck(b, sizeof(b), 0));45 }46 /* FALSE valid */47 {48 u8 b[] = { hdr_sz1(JSONB_FALSE, 0) };49 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));50 }51}52 53void test_jsonbValidityCheck_int_valid_and_errors(void){54 /* INT valid "123" */55 {56 u8 b[] = { hdr_sz1(JSONB_INT, 3), '1','2','3' };57 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));58 }59 /* INT valid "-7" */60 {61 u8 b[] = { hdr_sz1(JSONB_INT, 2), '-', '7' };62 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));63 }64 /* INT invalid lone '-' -> error at offset 1 */65 {66 u8 b[] = { hdr_sz1(JSONB_INT, 1), '-' };67 TEST_ASSERT_EQUAL_UINT32(1, runCheck(b, sizeof(b), 0));68 }69 /* INT invalid "1a3" -> error at 'a' which is at index 2 (0-based), so return 3 */70 {71 u8 b[] = { hdr_sz1(JSONB_INT, 3), '1', 'a', '3' };72 TEST_ASSERT_EQUAL_UINT32(3, runCheck(b, sizeof(b), 0));73 }74}75 76void test_jsonbValidityCheck_int5_variants(void){77 /* INT5 valid "0x1f" */78 {79 u8 b[] = { hdr_sz1(JSONB_INT5, 4), '0','x','1','f' };80 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));81 }82 /* INT5 valid "-0x1F" */83 {84 u8 b[] = { hdr_sz1(JSONB_INT5, 5), '-', '0','x','1','F' };85 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));86 }87 /* INT5 invalid missing leading '0': "1x0" -> error at i+1 = 1 */88 {89 u8 b[] = { hdr_sz1(JSONB_INT5, 3), '1','x','0' };90 TEST_ASSERT_EQUAL_UINT32(1, runCheck(b, sizeof(b), 0));91 }92 /* INT5 invalid wrong prefix "0y0" -> error returns j+2, here j=1 so 3 */93 {94 u8 b[] = { hdr_sz1(JSONB_INT5, 3), '0','y','0' };95 TEST_ASSERT_EQUAL_UINT32(3, runCheck(b, sizeof(b), 0));96 }97 /* INT5 invalid non-hex "0xG" -> error at index 3 -> returns 4 */98 {99 u8 b[] = { hdr_sz1(JSONB_INT5, 3), '0','x','G' };100 TEST_ASSERT_EQUAL_UINT32(4, runCheck(b, sizeof(b), 0));101 }102}103 104void test_jsonbValidityCheck_float_variants(void){105 /* FLOAT valid "1.2" */106 {107 u8 b[] = { hdr_sz1(JSONB_FLOAT, 3), '1','.','2' };108 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));109 }110 /* FLOAT valid "3e+5" */111 {112 u8 b[] = { hdr_sz1(JSONB_FLOAT, 4), '3','e','+','5' };113 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));114 }115 /* FLOAT invalid no '.' or 'e': "12" -> final seen==0 => i+1 = 1 */116 {117 u8 b[] = { hdr_sz1(JSONB_FLOAT, 2), '1','2' };118 TEST_ASSERT_EQUAL_UINT32(1, runCheck(b, sizeof(b), 0));119 }120 /* FLOAT invalid "0" too short -> sz<2 => i+1 = 1 */121 {122 u8 b[] = { hdr_sz1(JSONB_FLOAT, 1), '0' };123 TEST_ASSERT_EQUAL_UINT32(1, runCheck(b, sizeof(b), 0));124 }125 /* FLOAT invalid trailing '.' in RFC-8259 float: "1." -> error at '.' => index 2 => return 3 */126 {127 u8 b[] = { hdr_sz1(JSONB_FLOAT, 2), '1','.' };128 TEST_ASSERT_EQUAL_UINT32(3, runCheck(b, sizeof(b), 0));129 }130 /* FLOAT5 valid leading '.' ".5" */131 {132 u8 b[] = { hdr_sz1(JSONB_FLOAT5, 2), '.','5' };133 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));134 }135 /* FLOAT5 valid "1." (allowed in JSON5) */136 {137 u8 b[] = { hdr_sz1(JSONB_FLOAT5, 2), '1','.' };138 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));139 }140}141 142void test_jsonbValidityCheck_text_variants(void){143 /* TEXT valid "abc" */144 {145 u8 b[] = { hdr_sz1(JSONB_TEXT, 3), 'a','b','c' };146 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));147 }148 /* TEXT invalid backslash "a\\b" -> error at backslash index 2 -> return 3 */149 {150 u8 b[] = { hdr_sz1(JSONB_TEXT, 3), 'a','\\','b' };151 TEST_ASSERT_EQUAL_UINT32(3, runCheck(b, sizeof(b), 0));152 }153}154 155void test_jsonbValidityCheck_textj_variants(void){156 /* TEXTJ valid with escapes: "a\\n" */157 {158 u8 b[] = { hdr_sz1(JSONB_TEXTJ, 3), 'a','\\','n' };159 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));160 }161 /* TEXTJ valid \\u0041 */162 {163 u8 b[] = { hdr_sz1(JSONB_TEXTJ, 6), '\\','u','0','0','4','1' };164 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));165 }166 /* TEXTJ invalid unescaped double-quote: a"b -> error at quote index 2 => return 3 */167 {168 u8 b[] = { hdr_sz1(JSONB_TEXTJ, 3), 'a','"','b' };169 TEST_ASSERT_EQUAL_UINT32(3, runCheck(b, sizeof(b), 0));170 }171 /* TEXTJ invalid control char 0x1F */172 {173 u8 b[] = { hdr_sz1(JSONB_TEXTJ, 1), 0x1F };174 TEST_ASSERT_EQUAL_UINT32(2, runCheck(b, sizeof(b), 0));175 }176 /* TEXTJ invalid dangling backslash at end: "\\" -> error at j+1 where j=1 => 2 */177 {178 u8 b[] = { hdr_sz1(JSONB_TEXTJ, 1), '\\' };179 TEST_ASSERT_EQUAL_UINT32(2, runCheck(b, sizeof(b), 0));180 }181 /* TEXTJ invalid bad unicode escape: "\\u12G4" -> bad hex at 'G' index 4 => return 5 */182 {183 u8 b[] = { hdr_sz1(JSONB_TEXTJ, 6), '\\','u','1','2','G','4' };184 TEST_ASSERT_EQUAL_UINT32(5, runCheck(b, sizeof(b), 0));185 }186}187 188void test_jsonbValidityCheck_text5_variants(void){189 /* TEXT5 valid \\x41 */190 {191 u8 b[] = { hdr_sz1(JSONB_TEXT5, 4), '\\','x','4','1' };192 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));193 }194 /* TEXT5 valid \\v */195 {196 u8 b[] = { hdr_sz1(JSONB_TEXT5, 2), '\\','v' };197 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));198 }199}200 201void test_jsonbValidityCheck_textraw_always_ok(void){202 /* TEXTRAW accepts any bytes */203 {204 u8 b[] = { hdr_sz1(JSONB_TEXTRAW, 4), 'a','"','\n','\\' };205 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));206 }207}208 209void test_jsonbValidityCheck_array_valid_and_errors(void){210 /* ARRAY valid: [ INT "12", TEXT "ab" ] */211 {212 u8 elem1[] = { hdr_sz1(JSONB_INT, 2), '1','2' };213 u8 elem2[] = { hdr_sz1(JSONB_TEXT, 2), 'a','b' };214 u8 b[1 + sizeof(elem1) + sizeof(elem2)];215 b[0] = hdr_sz1(JSONB_ARRAY, (u8)(sizeof(elem1)+sizeof(elem2)));216 memcpy(&b[1], elem1, sizeof(elem1));217 memcpy(&b[1+sizeof(elem1)], elem2, sizeof(elem2));218 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));219 }220 /* ARRAY invalid: subelement declares size too big for remaining payload */221 {222 u8 sub[] = { hdr_sz1(JSONB_INT, 2), '1' }; /* header says 2, only 1 byte provided */223 u8 b[1 + sizeof(sub)];224 b[0] = hdr_sz1(JSONB_ARRAY, (u8)sizeof(sub)); /* payload size is what we actually provide */225 memcpy(&b[1], sub, sizeof(sub));226 /* Expect error at start of subelement: j = 1 -> j+1 = 2 */227 TEST_ASSERT_EQUAL_UINT32(2, runCheck(b, sizeof(b), 0));228 }229}230 231void test_jsonbValidityCheck_object_valid_and_errors(void){232 /* OBJECT valid: {"k":1} with TEXT key and INT value */233 {234 u8 key[] = { hdr_sz1(JSONB_TEXT, 1), 'k' };235 u8 val[] = { hdr_sz1(JSONB_INT, 1), '1' };236 u8 b[1 + sizeof(key) + sizeof(val)];237 b[0] = hdr_sz1(JSONB_OBJECT, (u8)(sizeof(key)+sizeof(val)));238 memcpy(&b[1], key, sizeof(key));239 memcpy(&b[1+sizeof(key)], val, sizeof(val));240 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));241 }242 /* OBJECT invalid: key is not text (INT), should error at start of key -> return 2 */243 {244 u8 keyBad[] = { hdr_sz1(JSONB_INT, 1), '1' };245 u8 val[] = { hdr_sz1(JSONB_INT, 1), '2' };246 u8 b[1 + sizeof(keyBad) + sizeof(val)];247 b[0] = hdr_sz1(JSONB_OBJECT, (u8)(sizeof(keyBad)+sizeof(val)));248 memcpy(&b[1], keyBad, sizeof(keyBad));249 memcpy(&b[1+sizeof(keyBad)], val, sizeof(val));250 TEST_ASSERT_EQUAL_UINT32(2, runCheck(b, sizeof(b), 0));251 }252 /* OBJECT invalid: odd number of elements (key only) -> error at j+1 where j==k==iEnd, iEnd=1+2=3 => returns 4 */253 {254 u8 key[] = { hdr_sz1(JSONB_TEXT, 1), 'k' };255 u8 b[1 + sizeof(key)];256 b[0] = hdr_sz1(JSONB_OBJECT, (u8)sizeof(key));257 memcpy(&b[1], key, sizeof(key));258 TEST_ASSERT_EQUAL_UINT32(4, runCheck(b, sizeof(b), 0));259 }260}261 262void test_jsonbValidityCheck_extended_headers(void){263 /* TEXT with 1-byte size (selector 12), size=3 */264 {265 u8 b[] = { hdr_sel(JSONB_TEXT, 12), 3, 'a','b','c' };266 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));267 }268 /* TEXT with 2-byte size (selector 13), size=3 */269 {270 u8 b[] = { hdr_sel(JSONB_TEXT, 13), 0, 3, 'x','y','z' };271 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));272 }273 /* TEXT with 4-byte size (selector 14), size=3 */274 {275 u8 b[] = { hdr_sel(JSONB_TEXT, 14), 0,0,0,3, '1','2','3' };276 TEST_ASSERT_EQUAL_UINT32(0, runCheck(b, sizeof(b), 0));277 }278}279 280void test_jsonbValidityCheck_array_with_truncated_extended_header(void){281 /* ARRAY payload begins with an element using selector 12 but truncated, causing jsonbPayloadSize to return 0 */282 {283 u8 sub_trunc[] = { hdr_sel(JSONB_INT, 12) }; /* missing size byte */284 u8 b[1 + sizeof(sub_trunc)];285 b[0] = hdr_sz1(JSONB_ARRAY, (u8)sizeof(sub_trunc)); /* payload size = 1 */286 memcpy(&b[1], sub_trunc, sizeof(sub_trunc));287 /* Expect error at start of subelement: index 1 -> return 2 */288 TEST_ASSERT_EQUAL_UINT32(2, runCheck(b, sizeof(b), 0));289 }290}291 292void test_jsonbValidityCheck_depth_limit(void){293 /* Any element with iDepth > JSON_MAX_DEPTH returns i+1 (1) */294 {295 u8 b[] = { hdr_sz1(JSONB_NULL, 0) };296 TEST_ASSERT_EQUAL_UINT32(1, runCheck(b, sizeof(b), JSON_MAX_DEPTH+1));297 }298}299 300int main(void){301 UNITY_BEGIN();302 RUN_TEST(test_jsonbValidityCheck_valid_null_true_false);303 RUN_TEST(test_jsonbValidityCheck_int_valid_and_errors);304 RUN_TEST(test_jsonbValidityCheck_int5_variants);305 RUN_TEST(test_jsonbValidityCheck_float_variants);306 RUN_TEST(test_jsonbValidityCheck_text_variants);307 RUN_TEST(test_jsonbValidityCheck_textj_variants);308 RUN_TEST(test_jsonbValidityCheck_text5_variants);309 RUN_TEST(test_jsonbValidityCheck_textraw_always_ok);310 RUN_TEST(test_jsonbValidityCheck_array_valid_and_errors);311 RUN_TEST(test_jsonbValidityCheck_object_valid_and_errors);312 RUN_TEST(test_jsonbValidityCheck_extended_headers);313 RUN_TEST(test_jsonbValidityCheck_array_with_truncated_extended_header);314 RUN_TEST(test_jsonbValidityCheck_depth_limit);315 return UNITY_END();316}