Skip to content

Commit

Permalink
Merge pull request #25 from Zondax/null_boxes
Browse files Browse the repository at this point in the history
Null boxes
  • Loading branch information
ftheirs authored Jun 19, 2023
2 parents 83bbcb2 + 7b0f126 commit 95b9258
Show file tree
Hide file tree
Showing 15 changed files with 279,275 additions and 279,963 deletions.
2 changes: 1 addition & 1 deletion app/Makefile.version
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ APPVERSION_M=2
# This is the `spec_version` field of `Runtime`
APPVERSION_N=1
# This is the patch version of this release
APPVERSION_P=7
APPVERSION_P=8
45 changes: 33 additions & 12 deletions app/src/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,38 @@ static parser_error_t parser_printTxType(const parser_context_t *ctx, char *outK
return parser_ok;
}

static parser_error_t parser_printBoxes(char *outKey, uint16_t outKeyLen, char *outVal, uint16_t outValLen, uint8_t displayIdx,
uint8_t pageIdx, uint8_t *pageCount, txn_application *application) {
if (outKey == NULL || outVal == NULL || application ==NULL) {
return parser_unexpected_error;
}

const uint8_t tmpIdx = displayIdx - IDX_BOXES;
if (tmpIdx >= MAX_FOREIGN_APPS) return parser_unexpected_value;

snprintf(outKey, outKeyLen, "Box %d", application->boxes[tmpIdx].i);

if (application->boxes[tmpIdx].n != NULL && application->boxes[tmpIdx].n_len > 0) {

bool printable = true;
for (uint16_t j = 0; j < application->boxes[tmpIdx].n_len; j++) {
printable &= IS_PRINTABLE(*(application->boxes[tmpIdx].n + j));
}

if (printable) {
pageStringExt(outVal, outValLen, (const char*) application->boxes[tmpIdx].n,
application->boxes[tmpIdx].n_len, pageIdx, pageCount);
} else {
base64_encode((char*) application->boxes[tmpIdx].n, application->boxes[tmpIdx].n_len, outVal, outValLen);
}
} else {
char null_box[8] = {0};
base64_encode(null_box, sizeof(null_box), outVal, outValLen);
}

return parser_ok;
}

static parser_error_t parser_printCommonParams(const parser_tx_t *parser_tx_obj,
uint8_t displayIdx,
char *outKey, uint16_t outKeyLen,
Expand Down Expand Up @@ -562,18 +594,7 @@ static parser_error_t parser_printTxApplication(parser_context_t *ctx,
return parser_ok;

case IDX_BOXES: {
const uint8_t tmpIdx = displayIdx - IDX_BOXES;
// Check max index
if (tmpIdx >= MAX_FOREIGN_APPS) return parser_unexpected_value;
if (tmpIdx == 0){
snprintf(outKey, outKeyLen, "Box");
}
else{
snprintf(outKey, outKeyLen, "Box %d", tmpIdx);
}
b64hash_data((unsigned char*) application->boxes[tmpIdx].n, application->boxes[tmpIdx].n_len, buff, sizeof(buff));
pageString(outVal, outValLen, buff, pageIdx, pageCount);
return parser_ok;
return parser_printBoxes(outKey, outKeyLen, outVal, outValLen, displayIdx, pageIdx, pageCount, application);
}

case IDX_FOREIGN_APP: {
Expand Down
182 changes: 120 additions & 62 deletions app/src/parser_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ DEC_READFIX_UNSIGNED(32);
DEC_READFIX_UNSIGNED(64);

static parser_error_t addItem(uint8_t displayIdx);
static parser_error_t _findKey(parser_context_t *c, const char *key);

#define DISPLAY_ITEM(type, len, counter) \
for(uint8_t j = 0; j < len; j++) { \
Expand Down Expand Up @@ -696,65 +697,68 @@ parser_error_t _readArrayU64(parser_context_t *c, uint64_t elements[], uint8_t *
return parser_ok;
}

__Z_INLINE parser_error_t _readBoxElement(parser_context_t *c, box *box) {

uint8_t key[2] = {0};
uint16_t mapSize = 0;
CHECK_ERROR(_readMapSize(c, &mapSize))
box->i = 0;
box->n_len = 0;
box->n = NULL;

for (uint16_t index = 0; index < mapSize; index++) {
CHECK_ERROR(_readString(c, key, sizeof(key)))
if (strncmp((char*)key, KEY_APP_BOX_INDEX, sizeof(KEY_APP_BOX_INDEX)) == 0) {
CHECK_ERROR(_readUInt8(c, &box->i))

} else if (strncmp((char*)key, KEY_APP_BOX_NAME, sizeof(KEY_APP_BOX_NAME)) == 0) {
CHECK_ERROR(_getPointerBin(c, &box->n, &box->n_len))

if (box->n_len > BOX_NAME_MAX_LENGTH) {
return parser_value_out_of_range;
}
} else {
return parser_unexpected_error;
}
}

return parser_ok;
}

parser_error_t _readBoxes(parser_context_t *c, box boxes[], uint8_t *num_elements)
{
CHECK_ERROR(_readArraySize(c, num_elements))
if (*num_elements > MAX_FOREIGN_APPS) {
return parser_msgpack_array_too_big;
}
uint16_t previous_offset = c->offset;

for (size_t j = 0; j < *num_elements; j++) {
CHECK_ERROR(_findKeyFromOffset(c, KEY_APP_BOX_INDEX, previous_offset))
previous_offset = c->offset;
CHECK_ERROR(_readUInt8(c, &boxes[j].i))
CHECK_ERROR(_findKeyFromOffset(c, KEY_APP_BOX_NAME, previous_offset))
CHECK_ERROR(_getPointerBin(c, &boxes[j].n, &boxes[j].n_len))
previous_offset = c->offset;
CHECK_ERROR(_readBoxElement(c, &boxes[j]))
}

return parser_ok;
}

static parser_error_t _readTxType(parser_context_t *c, parser_tx_t *v)
{
uint8_t buff[100] = {0};
uint8_t buffLen = sizeof(buff);
uint8_t typeStr[50] = {0};
uint8_t typeStrLen = sizeof(typeStr);
uint16_t currentOffset = c->offset;
c->offset = 0;

for (size_t offset = 0; offset < c->bufferLen; offset++) {
if (_readString(c, buff, buffLen) == parser_ok) {
if (strncmp((char*)buff, KEY_COMMON_TYPE, sizeof(KEY_COMMON_TYPE)) == 0) {
if (_readString(c, typeStr, typeStrLen) == parser_ok) {
if (strncmp((char *) typeStr, KEY_TX_PAY, sizeof(KEY_TX_PAY)) == 0) {
v->type = TX_PAYMENT;
break;
} else if (strncmp((char *) typeStr, KEY_TX_KEYREG, sizeof(KEY_TX_KEYREG)) == 0) {
v->type = TX_KEYREG;
break;
} else if (strncmp((char *) typeStr, KEY_TX_ASSET_XFER, sizeof(KEY_TX_ASSET_XFER)) == 0) {
v->type = TX_ASSET_XFER;
break;
} else if (strncmp((char *) typeStr, KEY_TX_ASSET_FREEZE, sizeof(KEY_TX_ASSET_FREEZE)) == 0) {
v->type = TX_ASSET_FREEZE;
break;
} else if (strncmp((char *) typeStr, KEY_TX_ASSET_CONFIG, sizeof(KEY_TX_ASSET_CONFIG)) == 0) {
v->type = TX_ASSET_CONFIG;
break;
} else if (strncmp((char *) typeStr, KEY_TX_APPLICATION, sizeof(KEY_TX_APPLICATION)) == 0) {
v->type = TX_APPLICATION;
break;
}
}
}
}
c->offset = offset + 1;
}

if(v->type == TX_UNKNOWN) {
// Return buffer to previous offset if key is not found
c->offset = currentOffset;
char typeStr[10] = {0};
CHECK_ERROR(_findKey(c, KEY_COMMON_TYPE))
CHECK_ERROR(_readString(c, (uint8_t*) typeStr, sizeof(typeStr)))

if (strncmp(typeStr, KEY_TX_PAY, sizeof(KEY_TX_PAY)) == 0) {
v->type = TX_PAYMENT;
} else if (strncmp(typeStr, KEY_TX_KEYREG, sizeof(KEY_TX_KEYREG)) == 0) {
v->type = TX_KEYREG;
} else if (strncmp(typeStr, KEY_TX_ASSET_XFER, sizeof(KEY_TX_ASSET_XFER)) == 0) {
v->type = TX_ASSET_XFER;
} else if (strncmp(typeStr, KEY_TX_ASSET_FREEZE, sizeof(KEY_TX_ASSET_FREEZE)) == 0) {
v->type = TX_ASSET_FREEZE;
} else if (strncmp(typeStr, KEY_TX_ASSET_CONFIG, sizeof(KEY_TX_ASSET_CONFIG)) == 0) {
v->type = TX_ASSET_CONFIG;
} else if (strncmp(typeStr, KEY_TX_APPLICATION, sizeof(KEY_TX_APPLICATION)) == 0) {
v->type = TX_APPLICATION;
} else {
v->type = TX_UNKNOWN;
return parser_no_data;
}

Expand Down Expand Up @@ -819,27 +823,81 @@ static parser_error_t _readTxCommonParams(parser_context_t *c, parser_tx_t *v)
return parser_ok;
}

parser_error_t _findKey(parser_context_t *c, const char *key)
{
return _findKeyFromOffset(c, key, 0);
static parser_error_t _verifyValue(parser_context_t *c) {
if (c == NULL) return parser_unexpected_error;

CHECK_APP_CANARY()

union {
uint8_t u8_number;
uint16_t u16_number;
uint64_t u64_number;
} tmp;

uint8_t valueType = 0;
CHECK_ERROR(_readUInt8(c, &valueType))

// Point to where value type is defined
c->offset--;

if (valueType <= FIXINT_127 || (valueType >= UINT8 && valueType <= UINT64)) {
CHECK_ERROR(_readInteger(c, &tmp.u64_number))

} else if (valueType <= FIXMAP_15 || valueType == MAP16) {
CHECK_ERROR(_readMapSize(c, &tmp.u16_number))
const uint16_t mapLen = tmp.u16_number;
for (uint16_t i = 0; i < mapLen; i++) {
// Check key
CHECK_ERROR(_verifyValue(c))
// Check value
CHECK_ERROR(_verifyValue(c))
}

} else if (valueType <= FIXARR_15 || valueType == ARR16) {
CHECK_ERROR(_readArraySize(c, &tmp.u8_number))
const uint8_t arrLen = tmp.u8_number;
for (uint8_t i = 0; i < arrLen; i++) {
CHECK_ERROR(_verifyValue(c))
}

} else if (valueType <= FIXSTR_31) {
c->offset++;
const uint8_t strLen = valueType - FIXSTR_0;
CHECK_ERROR(_verifyBytes(c, strLen))

} else if (valueType == STR8) {
c->offset++;
uint8_t strLen = 0;
CHECK_ERROR(_readUInt8(c, &strLen))
CHECK_ERROR(_verifyBytes(c, strLen))

} else if (valueType == BOOL_FALSE || valueType == BOOL_TRUE) {
CHECK_ERROR(_readBool(c, &tmp.u8_number))

} else if (valueType == BIN8 || valueType == BIN16) {
CHECK_ERROR(_verifyBin(c, &tmp.u16_number, UINT16_MAX))

} else {
return parser_unexpected_value;
}

return parser_ok;
}
parser_error_t _findKey(parser_context_t *c, const char *key) {
uint8_t tmpKey[20] = {0};

parser_error_t _findKeyFromOffset(parser_context_t *c, const char *key, const uint16_t searchOffset)
{
uint8_t buff[100] = {0};
uint8_t buffLen = sizeof(buff);
uint16_t currentOffset = c->offset;
// Process buffer from start
c->offset = 0;
for (size_t offset = searchOffset; offset < c->bufferLen; offset++) {
if (_readString(c, buff, buffLen) == parser_ok) {
if (strlen((char*)buff) == strlen(key) && strncmp((char*)buff, key, strlen(key)) == 0) {
return parser_ok;
}
uint16_t keysLen = 0;
CHECK_ERROR(_readMapSize(c, &keysLen))
for (uint16_t i = 0; i < keysLen; i++) {
CHECK_ERROR(_readString(c, tmpKey, sizeof(tmpKey)))
if (strncmp((char*)tmpKey, key, strlen(key)) == 0) {
return parser_ok;
}
c->offset = offset + 1;
CHECK_ERROR(_verifyValue(c))
}
// Return buffer to previous offset if key is not found
c->offset = currentOffset;

return parser_no_data;
}

Expand Down
2 changes: 0 additions & 2 deletions app/src/parser_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ parser_error_t _readString(parser_context_t *c, uint8_t *buff, uint16_t buffLen)
parser_error_t _readInteger(parser_context_t *c, uint64_t* value);
parser_error_t _readBool(parser_context_t *c, uint8_t *value);
parser_error_t _readBinFixed(parser_context_t *c, uint8_t *buff, uint16_t bufferLen);
parser_error_t _findKey(parser_context_t *c, const char *key);
parser_error_t _findKeyFromOffset(parser_context_t *c, const char *key, const uint16_t searchOffset);

parser_error_t _getAccount(parser_context_t *c, uint8_t* account, uint8_t account_idx, uint8_t num_accounts);
parser_error_t _getAppArg(parser_context_t *c, uint8_t **args, uint16_t* args_len, uint8_t args_idx, uint16_t max_args_len, uint8_t max_array_len);
Expand Down
2 changes: 2 additions & 0 deletions app/src/parser_txdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ typedef enum tx_type_e {
#define KEY_SCHEMA_NUI "nui"
#define KEY_SCHEMA_NBS "nbs"

#define BOX_NAME_MAX_LENGTH 64


typedef enum oncompletion {
NOOPOC = 0,
Expand Down
Loading

0 comments on commit 95b9258

Please sign in to comment.