Skip to content

Commit 0c94895

Browse files
authored
Merge pull request #39 from Zondax/bugfix-decoding
Fix RLP & JSON decoding
2 parents 2241a84 + c80bb23 commit 0c94895

File tree

5 files changed

+33
-28
lines changed

5 files changed

+33
-28
lines changed

app/src/parser.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ void __assert_fail(const char * assertion, const char * file, unsigned int line,
2929
}
3030
#endif
3131

32+
#define FLOW_PUBKEY_SIZE 150
33+
3234
parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t dataLen) {
3335
CHECK_PARSER_ERR(parser_init(ctx, data, dataLen))
3436
return _read(ctx, &parser_tx_obj);
@@ -86,7 +88,7 @@ parser_error_t parser_printArgumentPublicKey(const parser_context_t *argumentCtx
8688
parsed_json_t parsedJson = {false};
8789
CHECK_PARSER_ERR(json_parse(&parsedJson, (char *) argumentCtx->buffer, argumentCtx->bufferLen));
8890

89-
char bufferUI[130];
91+
char bufferUI[FLOW_PUBKEY_SIZE];
9092
CHECK_PARSER_ERR(json_extractPubKey(bufferUI, sizeof(bufferUI), &parsedJson, 0))
9193
pageString(outVal, outValLen, bufferUI, pageIdx, pageCount);
9294

@@ -118,7 +120,7 @@ parser_error_t parser_printArgumentPublicKeys(const parser_context_t *argumentCt
118120
zemu_log_stack("PublicKeys");
119121

120122
uint16_t arrayElementToken;
121-
char bufferUI[130];
123+
char bufferUI[FLOW_PUBKEY_SIZE];
122124
CHECK_PARSER_ERR(array_get_nth_element(&parsedJson, internalTokenElementIdx, argumentIndex, &arrayElementToken))
123125
CHECK_PARSER_ERR(json_extractPubKey(bufferUI, sizeof(bufferUI), &parsedJson, arrayElementToken))
124126
pageString(outVal, outValLen, bufferUI, pageIdx, pageCount);

app/src/parser_impl.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ parser_error_t _readGasLimit(parser_context_t *c, flow_gaslimit_t *v) {
335335

336336
CHECK_PARSER_ERR(rlp_decode(c, &ctx_local, &kind, &bytesConsumed));
337337
CTX_CHECK_AND_ADVANCE(c, bytesConsumed)
338-
CHECK_KIND(kind, kind_byte)
338+
CHECK_KIND(kind, kind_string)
339339

340340
CHECK_PARSER_ERR(rlp_readUInt64(&ctx_local, kind, v))
341341

@@ -363,7 +363,7 @@ parser_error_t _readProposalKeyId(parser_context_t *c, flow_proposal_keyid_t *v)
363363

364364
CHECK_PARSER_ERR(rlp_decode(c, &ctx_local, &kind, &bytesConsumed));
365365
CTX_CHECK_AND_ADVANCE(c, bytesConsumed)
366-
CHECK_KIND(kind, kind_byte)
366+
CHECK_KIND(kind, kind_string)
367367

368368
CHECK_PARSER_ERR(rlp_readUInt64(&ctx_local, kind, v))
369369

@@ -379,7 +379,7 @@ parser_error_t _readProposalKeySequenceNumber(parser_context_t *c, flow_proposal
379379

380380
CHECK_PARSER_ERR(rlp_decode(c, &ctx_local, &kind, &bytesConsumed));
381381
CTX_CHECK_AND_ADVANCE(c, bytesConsumed)
382-
CHECK_KIND(kind, kind_byte)
382+
CHECK_KIND(kind, kind_string)
383383

384384
CHECK_PARSER_ERR(rlp_readUInt64(&ctx_local, kind, v))
385385

app/src/rlp.c

+19-18
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ parser_error_t rlp_decode(
3636
uint8_t p = *outputPayload->buffer;
3737

3838
if (p >= 0 && p <= 0x7F) {
39-
*outputKind = kind_byte;
39+
*outputKind = kind_string;
4040
outputPayload->bufferLen = 1;
4141
outputPayload->buffer += 0;
4242
*bytesConsumed = 1; // 1 byte to consume from the stream
@@ -99,7 +99,7 @@ parser_error_t rlp_decode(
9999
}
100100

101101
parser_error_t rlp_readByte(const parser_context_t *ctx, rlp_kind_e kind, uint8_t *value) {
102-
if (kind != kind_byte) {
102+
if (kind != kind_string) {
103103
return parser_rlp_error_invalid_kind;
104104
}
105105

@@ -118,28 +118,29 @@ parser_error_t rlp_readByte(const parser_context_t *ctx, rlp_kind_e kind, uint8_
118118
parser_error_t rlp_readUInt64(const parser_context_t *ctx,
119119
rlp_kind_e kind,
120120
uint64_t *value) {
121-
if (kind == kind_string) {
122-
*value = 0;
123-
124-
if (ctx->bufferLen != 8) {
125-
return parser_rlp_error_invalid_value_len;
126-
}
127-
128-
for (uint8_t i = 0; i < 8; i++) {
129-
*value <<= 8u;
130-
*value += *(ctx->buffer + ctx->offset + i);
131-
}
132-
133-
*value <<= 8u;
134-
return parser_ok;
121+
if (kind != kind_string) {
122+
return parser_rlp_error_invalid_kind;
135123
}
136124

137-
if (kind == kind_byte) {
125+
// handle case when string is a single byte
126+
if (ctx->bufferLen == 1) {
138127
uint8_t tmp;
139128
CHECK_PARSER_ERR(rlp_readByte(ctx, kind, &tmp))
140129
*value = tmp;
141130
return parser_ok;
142131
}
143132

144-
return parser_rlp_error_invalid_kind;
133+
// max size of uint64_t is 8 bytes
134+
if (ctx->bufferLen > 8) {
135+
return parser_rlp_error_invalid_value_len;
136+
}
137+
138+
*value = 0;
139+
140+
for (uint8_t i = 0; i < ctx->bufferLen; i++) {
141+
*value <<= 8u;
142+
*value += *(ctx->buffer + ctx->offset + i);
143+
}
144+
145+
return parser_ok;
145146
}

app/src/rlp.h

-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ extern "C" {
2525

2626
typedef enum {
2727
kind_unknown = 0,
28-
kind_byte,
2928
kind_string,
3029
kind_list,
3130
} rlp_kind_e;

tests/rlp.cpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,18 @@ class RLPDecodeTest : public testing::TestWithParam<RLPValueTestCase> {
3737
void TearDown() override {}
3838
};
3939

40+
// Test cases adapted from official Ethereum RLP tests: https://github.com/ethereum/tests/blob/develop/RLPTests/rlptest.json
4041
INSTANTIATE_TEST_SUITE_P(
4142
InstantiationName,
4243
RLPDecodeTest,
4344
Values(
44-
RLPValueTestCase{"00", kind_byte, 1, 0, 1},
45-
RLPValueTestCase{"01", kind_byte, 1, 0, 1},
46-
RLPValueTestCase{"7F", kind_byte, 1, 0, 1},
45+
RLPValueTestCase{"00", kind_string, 1, 0, 1}, // Byte string (00)
46+
RLPValueTestCase{"01", kind_string, 1, 0, 1}, // Byte string (01)
47+
RLPValueTestCase{"7F", kind_string, 1, 0, 1}, // Byte string (7F)
48+
49+
RLPValueTestCase{"80", kind_string, 0, 1, 1}, // Empty string ("")
50+
RLPValueTestCase{"83646F67", kind_string, 3, 1, 4}, // Short string ("dog")
4751

48-
RLPValueTestCase{"80", kind_string, 0, 1, 1},
4952
RLPValueTestCase{"B7"
5053
"0000000000000000000000000000000000000000000000000000000000000000"
5154
"0000000000000000000000000000000000000000000000000000000000000000"

0 commit comments

Comments
 (0)