From 304b4eed909962ada1299b2396d78023faaa09dd Mon Sep 17 00:00:00 2001 From: Soroush Safari Loaliyan Date: Wed, 24 Jun 2026 12:06:55 -0700 Subject: [PATCH] Add bounds checks to standard JSON array iterator --- cujson/query/query_iterator_standard_json.cpp | 110 +++++++++++++++--- .../query/query_iterator_standard_json.cpp | 108 +++++++++++++++-- 2 files changed, 194 insertions(+), 24 deletions(-) diff --git a/cujson/query/query_iterator_standard_json.cpp b/cujson/query/query_iterator_standard_json.cpp index 9ef1efa..450ed01 100644 --- a/cujson/query/query_iterator_standard_json.cpp +++ b/cujson/query/query_iterator_standard_json.cpp @@ -146,14 +146,33 @@ void cuJSONIterator::freeJson(){ } char cuJSONIterator::getChar(int idx){ - if( inputJSON[structural[idx] - 1] == '\n' ) return ','; + if(idx < 0 || idx >= totalResultSize || structural == NULL || inputJSON == NULL){ + return '\0'; + } else if (idx == totalResultSize - 1) return ']'; else if (idx == 0) return '['; - else return inputJSON[structural[idx] - 1]; -} + int pos = structural[idx] - 1; + if(pos < 0 || pos >= fileSize){ + return '\0'; + } + + else if(inputJSON[pos] == '\n'){ + return ','; + } + + else return inputJSON[pos];} int cuJSONIterator::jumpOpeningForward(int idx){ - return pair_pos[idx]; + if(idx < 0 || idx >= totalResultSize || pair_pos == NULL){ + return -1; + } + + int pairNode = pair_pos[idx]; + if(pairNode < 0 || pairNode >= totalResultSize){ + return -1; + } + + return pairNode; } int cuJSONIterator::jumpSpacesForward(int pos){ @@ -250,37 +269,102 @@ void cuJSONIterator::reset(){ } int cuJSONIterator::gotoArrayIndex(int index){ + if(index < 0){ + return 0; + } + + if(totalResultSize <= 0 || structural == NULL || pair_pos == NULL || inputJSON == NULL){ + return 0; + } + + if(node < 0 || node >= totalResultSize){ + return 0; + } + int total = index + 1; // total number of index that we have to go forward to get the requested index [started from 0] // +1 is for handling indexes [1,2,3,...], user will use [0,1,2,...] - char currentNodeChar = getChar(node); + int startNode = node; + int nextNode; + + char currentNodeChar = getChar(startNode); + if(currentNodeChar == '\0'){ + return 0; + } // cout << "currNodeChar: " << currentNodeChar <= totalResultSize){ + return 0; + } + + startNode++; + currentNodeChar = getChar(startNode); + if(currentNodeChar == '\0'){ + return 0; + } + } // next node - int nextNode = node+1; - char nextNodeChar = getChar(nextNode); + nextNode = startNode + 1; + if(nextNode < 0 || nextNode >= totalResultSize){ + return 0; + } + char nextNodeChar = getChar(nextNode); + if(nextNodeChar == '\0'){ + return 0; + } // cout << "nextNodeChar: " << nextNodeChar <= totalResultSize){ + return 0; + } // cout << "nxt->" << nextNodeChar <= totalResultSize){ + return 0; + } + + nextNode = pairNode; } - if(nextNodeChar == ',' || nextNodeChar == '\n'){ // no need for \n - total--; // go one node forward + + if(nextNodeChar == ',' || nextNodeChar == '\n'){ + total--; } nextNode++; + if(nextNode < 0 || nextNode >= totalResultSize){ + return 0; + } + nextNodeChar = getChar(nextNode); + if(nextNodeChar == '\0'){ + return 0; + } } // that means we achieve to requested index if(total == 1){ // cout << "curr node in total == 1 --> " << getChar(nextNode) <= totalResultSize){ + return 0; + } + + /* + * Reject empty-array access, for example gotoArrayIndex(0) on []. + */ + if(nextNodeChar == ']' && targetNode == startNode){ + return 0; + } + + node = targetNode; if(nextNodeChar == '{'){ nodeType = OBJECT; diff --git a/paper_reproduced/src/query/query_iterator_standard_json.cpp b/paper_reproduced/src/query/query_iterator_standard_json.cpp index bd5a405..2345196 100644 --- a/paper_reproduced/src/query/query_iterator_standard_json.cpp +++ b/paper_reproduced/src/query/query_iterator_standard_json.cpp @@ -163,14 +163,34 @@ void structural_iterator::freeJson(){ } char structural_iterator::getChar(int idx){ - if( inputJSON[structural[idx] - 1] == '\n' ) return ','; + if(idx < 0 || idx >= totalResultSize || structural == NULL || inputJSON == NULL){ + return '\0'; + } else if (idx == totalResultSize - 1) return ']'; else if (idx == 0) return '['; - else return inputJSON[structural[idx] - 1]; -} + + int pos = structural[idx] - 1; + if(pos < 0 || pos >= fileSize){ + return '\0'; + } + + else if(inputJSON[pos] == '\n'){ + return ','; + } + + else return inputJSON[pos];} int structural_iterator::jumpOpeningForward(int idx){ - return pair_pos[idx]; + if(idx < 0 || idx >= totalResultSize || pair_pos == NULL){ + return -1; + } + + int pairNode = pair_pos[idx]; + if(pairNode < 0 || pairNode >= totalResultSize){ + return -1; + } + + return pairNode; } int structural_iterator::jumpSpacesForward(int pos){ @@ -267,38 +287,104 @@ void structural_iterator::reset(){ } int structural_iterator::gotoArrayIndex(int index){ + if(index < 0){ + return 0; + } + + if(totalResultSize <= 0 || structural == NULL || pair_pos == NULL || inputJSON == NULL){ + return 0; + } + + if(node < 0 || node >= totalResultSize){ + return 0; + } int total = index + 1; // total number of index that we have to go forward to get the requested index [started from 0] // +1 is for handling indexes [1,2,3,...], user will use [0,1,2,...] - char currentNodeChar = getChar(node); + int startNode = node; + int nextNode; + + char currentNodeChar = getChar(startNode); + if(currentNodeChar == '\0'){ + return 0; + } // cout << "currNodeChar: " << currentNodeChar <= totalResultSize){ + return 0; + } + + startNode++; + currentNodeChar = getChar(startNode); + if(currentNodeChar == '\0'){ + return 0; + } + } + // next node - int nextNode = node+1; - char nextNodeChar = getChar(nextNode); + nextNode = startNode + 1; + if(nextNode < 0 || nextNode >= totalResultSize){ + return 0; + } + char nextNodeChar = getChar(nextNode); + if(nextNodeChar == '\0'){ + return 0; + } // cout << "nextNodeChar: " << nextNodeChar <= totalResultSize){ + return 0; + } // cout << "nxt->" << nextNodeChar <= totalResultSize){ + return 0; + } + + nextNode = pairNode; } if(nextNodeChar == ',' || nextNodeChar == '\n'){ // no need for \n total--; // go one node forward } nextNode++; + if(nextNode < 0 || nextNode >= totalResultSize){ + return 0; + } + nextNodeChar = getChar(nextNode); + if(nextNodeChar == '\0'){ + return 0; + } } // that means we achieve to requested index if(total == 1){ // cout << "curr node in total == 1 --> " << getChar(nextNode) <= totalResultSize){ + return 0; + } + + /* + * Reject empty-array access, for example gotoArrayIndex(0) on []. + */ + if(nextNodeChar == ']' && targetNode == startNode){ + return 0; + } + node = targetNode; if(nextNodeChar == '{'){ nodeType = OBJECT; }