Skip to content

Commit 5159ec3

Browse files
Parser: add a way to parse the current element again
We need to re-parse if the input buffer was too short to read the current element's information. When that happens, the current element will be CborInvalidType, so we can't easily resume. Signed-off-by: Thiago Macieira <[email protected]>
1 parent 87a7a93 commit 5159ec3

File tree

3 files changed

+77
-23
lines changed

3 files changed

+77
-23
lines changed

src/cbor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ CBOR_INLINE_API bool cbor_value_at_end(const CborValue *it)
344344
{ return it->remaining == 0; }
345345
CBOR_INLINE_API const uint8_t *cbor_value_get_next_byte(const CborValue *it)
346346
{ return it->source.ptr; }
347+
CBOR_API CborError cbor_value_reparse(CborValue *it);
347348
CBOR_API CborError cbor_value_advance_fixed(CborValue *it);
348349
CBOR_API CborError cbor_value_advance(CborValue *it);
349350
CBOR_INLINE_API bool cbor_value_is_container(const CborValue *it)

src/cborparser.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,13 @@ CborError cbor_parser_init_reader(const struct CborParserOperations *ops, CborPa
401401
* \sa cbor_value_at_end()
402402
*/
403403

404+
CborError cbor_value_reparse(CborValue *it)
405+
{
406+
if (it->flags & CborIteratorFlag_IteratingStringChunks)
407+
return CborNoError;
408+
return preparse_next_value_nodecrement(it);
409+
}
410+
404411
/**
405412
* \fn bool cbor_value_is_valid(const CborValue *it)
406413
*

tests/parser/tst_parser.cpp

Lines changed: 69 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ private slots:
8686

8787
void readerApi_data() { arrays_data(); }
8888
void readerApi();
89+
void reparse_data();
90+
void reparse();
8991

9092
// chunked string API
9193
void chunkedString_data();
@@ -108,8 +110,8 @@ private slots:
108110
void validation();
109111
void strictValidation_data();
110112
void strictValidation();
111-
void resumeParsing_data();
112-
void resumeParsing();
113+
void incompleteData_data();
114+
void incompleteData();
113115
void endPointer_data();
114116
void endPointer();
115117
void recursionLimit_data();
@@ -755,30 +757,25 @@ void tst_Parser::mapsAndArrays()
755757
"{_ 1: [_ " + expected + "], \"Hello\": {_ " + expected + ": (_ )}}");
756758
}
757759

758-
void tst_Parser::readerApi()
759-
{
760-
QFETCH(QByteArray, data);
761-
QFETCH(QString, expected);
762-
763-
struct Input {
764-
QByteArray data;
765-
int consumed;
766-
} input = { data, 0 };
760+
struct Input {
761+
QByteArray data;
762+
int consumed;
763+
};
767764

768-
CborParserOperations ops;
769-
ops.can_read_bytes = [](void *token, size_t len) {
765+
static const CborParserOperations byteArrayOps = {
766+
/* can_read_bytes = */ [](void *token, size_t len) {
770767
auto input = static_cast<Input *>(token);
771768
return input->data.size() - input->consumed >= int(len);
772-
};
773-
ops.read_bytes = [](void *token, void *dst, size_t offset, size_t len) {
769+
},
770+
/* read_bytes = */ [](void *token, void *dst, size_t offset, size_t len) {
774771
auto input = static_cast<Input *>(token);
775772
return memcpy(dst, input->data.constData() + input->consumed + offset, len);
776-
};
777-
ops.advance_bytes = [](void *token, size_t len) {
773+
},
774+
/* advance_bytes = */ [](void *token, size_t len) {
778775
auto input = static_cast<Input *>(token);
779776
input->consumed += int(len);
780-
};
781-
ops.transfer_string = [](void *token, const void **userptr, size_t offset, size_t len) {
777+
},
778+
/* transfer_string = */ [](void *token, const void **userptr, size_t offset, size_t len) {
782779
// ###
783780
auto input = static_cast<Input *>(token);
784781
if (input->data.size() - input->consumed < int(len + offset))
@@ -787,11 +784,60 @@ void tst_Parser::readerApi()
787784
*userptr = input->data.constData() + input->consumed;
788785
input->consumed += int(len);
789786
return CborNoError;
790-
};
787+
}
788+
};
789+
790+
void tst_Parser::readerApi()
791+
{
792+
QFETCH(QByteArray, data);
793+
QFETCH(QString, expected);
794+
795+
Input input = { data, 0 };
791796

792797
CborParser parser;
793798
CborValue first;
794-
CborError err = cbor_parser_init_reader(&ops, &parser, &first, &input);
799+
CborError err = cbor_parser_init_reader(&byteArrayOps, &parser, &first, &input);
800+
QCOMPARE(err, CborNoError);
801+
802+
QString decoded;
803+
err = parseOne(&first, &decoded);
804+
QCOMPARE(err, CborNoError);
805+
QCOMPARE(decoded, expected);
806+
807+
// check we consumed everything
808+
QCOMPARE(input.consumed, data.size());
809+
}
810+
811+
void tst_Parser::reparse_data()
812+
{
813+
// only one-item rows
814+
addColumns();
815+
addFixedData();
816+
}
817+
818+
void tst_Parser::reparse()
819+
{
820+
QFETCH(QByteArray, data);
821+
QFETCH(QString, expected);
822+
823+
Input input = { QByteArray(), 0 };
824+
CborParser parser;
825+
CborValue first;
826+
CborError err = cbor_parser_init_reader(&byteArrayOps, &parser, &first, &input);
827+
QCOMPARE(err, CborErrorUnexpectedEOF);
828+
829+
for (int i = 0; i < data.size(); ++i) {
830+
input.data = data.left(i);
831+
err = cbor_value_reparse(&first);
832+
if (err != CborErrorUnexpectedEOF)
833+
qDebug() << "At" << i;
834+
QCOMPARE(err, CborErrorUnexpectedEOF);
835+
QCOMPARE(input.consumed, 0);
836+
}
837+
838+
// now it should work
839+
input.data = data;
840+
err = cbor_value_reparse(&first);
795841
QCOMPARE(err, CborNoError);
796842

797843
QString decoded;
@@ -1707,7 +1753,7 @@ void tst_Parser::strictValidation()
17071753
QCOMPARE(err, expectedError);
17081754
}
17091755

1710-
void tst_Parser::resumeParsing_data()
1756+
void tst_Parser::incompleteData_data()
17111757
{
17121758
addColumns();
17131759
addFixedData();
@@ -1716,7 +1762,7 @@ void tst_Parser::resumeParsing_data()
17161762
addMapMixedData();
17171763
}
17181764

1719-
void tst_Parser::resumeParsing()
1765+
void tst_Parser::incompleteData()
17201766
{
17211767
QFETCH(QByteArray, data);
17221768
QFETCH(QString, expected);

0 commit comments

Comments
 (0)