Skip to content

Commit 2bb2dae

Browse files
committed
abi: decode signed numbers properly
1 parent 19f119b commit 2bb2dae

File tree

2 files changed

+24
-19
lines changed

2 files changed

+24
-19
lines changed

src/abi.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ ETH_OP eth_abi_bytes(struct eth_abi *abi, uint8_t *bytes, size_t *len) {
707707
ETH_OP eth_abi_mpint(struct eth_abi *abi, mp_int *mpint) {
708708
struct ethc_abi_dynamic_type *ctype = NULL;
709709
uint8_t buf[32] = {0}, size = 0;
710-
mp_int pow256, tmpint;
710+
mp_int mask, tmpint;
711711
ETH_OP op;
712712

713713
if (abi == NULL || mpint == NULL)
@@ -724,18 +724,18 @@ ETH_OP eth_abi_mpint(struct eth_abi *abi, mp_int *mpint) {
724724

725725
// if the mpint is a negative number
726726
if (mp_cmp_d(&tmpint, 0) == MP_LT) {
727-
if (mp_init(&pow256) != MP_OKAY) {
727+
if (mp_init(&mask) != MP_OKAY) {
728728
mp_clear(&tmpint);
729729
return ETH_ERR_MP;
730730
}
731731

732-
if (mp_2expt(&pow256, 256) != MP_OKAY) {
733-
mp_clear_multi(&tmpint, &pow256, NULL);
732+
if (mp_2expt(&mask, 256) != MP_OKAY) {
733+
mp_clear_multi(&tmpint, &mask, NULL);
734734
return ETH_ERR_MP;
735735
}
736736

737-
if (mp_add(&tmpint, &pow256, &tmpint) != MP_OKAY) {
738-
mp_clear_multi(&tmpint, &pow256, NULL);
737+
if (mp_add(&tmpint, &mask, &tmpint) != MP_OKAY) {
738+
mp_clear_multi(&tmpint, &mask, NULL);
739739
return ETH_ERR_MP;
740740
}
741741
}
@@ -767,21 +767,21 @@ ETH_OP eth_abi_mpint(struct eth_abi *abi, mp_int *mpint) {
767767
return ETH_ERR_MP;
768768

769769
// if the most significant bit is set (is negative)
770-
if (s_mp_get_bit(mpint, 0xff) == MP_YES) {
771-
if (mp_init(&pow256) != MP_OKAY)
770+
if (buf[0] & 0x80) {
771+
if (mp_init(&mask) != MP_OKAY)
772772
return ETH_ERR_MP;
773773

774-
if (mp_2expt(&pow256, 256) != MP_OKAY) {
775-
mp_clear(&pow256);
774+
if (mp_2expt(&mask, 256) != MP_OKAY) {
775+
mp_clear(&mask);
776776
return ETH_ERR_MP;
777777
}
778778

779-
if (mp_sub(mpint, &pow256, mpint) != MP_OKAY) {
780-
mp_clear(&pow256);
779+
if (mp_sub(mpint, &mask, mpint) != MP_OKAY) {
780+
mp_clear(&mask);
781781
return ETH_ERR_MP;
782782
}
783783

784-
mp_clear(&pow256);
784+
mp_clear(&mask);
785785
return ETH_OK;
786786
}
787787

test/test-eth-abi.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -247,13 +247,13 @@ void test_eth_abi_int64(void) {
247247

248248
void test_eth_abi_mpint(void) {
249249
struct eth_abi abi0={0}, abi1={0};
250-
mp_int int0, int1, int2, int3, int4;
250+
mp_int int0, int1, int2, int3, int4, int5, int6;
251251
size_t hexlen;
252252
char *hex;
253253

254254
diag("eth_abi_mpint()");
255255

256-
assert(mp_init_multi(&int0, &int1, &int2, &int3, &int4, NULL) == MP_OKAY);
256+
assert(mp_init_multi(&int0, &int1, &int2, &int3, &int4, &int5, &int6, NULL) == MP_OKAY);
257257

258258
assert(mp_read_radix(&int0, "ff", 16) == MP_OKAY);
259259
assert(mp_read_radix(&int1, "-256", 10) == MP_OKAY);
@@ -273,14 +273,19 @@ void test_eth_abi_mpint(void) {
273273
free(hex);
274274

275275
assert(eth_abi_from_hex(&abi1,
276-
"ffffffffffffffffffffffffffffffffffffffffffffffff830dcf6847e523d0", -1) == ETH_OK);
277-
assert(mp_read_radix(&int3, "-9003312033254005808", 10) == ETH_OK);
276+
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8dc56"
277+
"0000000000000000000000000000000000000000000000000000000001f9b628", -1) == ETH_OK);
278278

279+
assert(eth_abi_mpint(&abi1, &int3) == ETH_OK);
279280
assert(eth_abi_mpint(&abi1, &int4) == ETH_OK);
280281

281-
ok(mp_cmp(&int3, &int4) == MP_EQ, "decode -9003312033254005808");
282+
assert(mp_read_radix(&int5, "-467882", 10) == MP_OKAY);
283+
assert(mp_read_radix(&int6, "33142312", 10) == MP_OKAY);
282284

283-
mp_clear_multi(&int0, &int1, &int2, &int3, &int4, NULL);
285+
ok(mp_cmp(&int3, &int5) == MP_EQ, "decode -467882");
286+
ok(mp_cmp(&int4, &int6) == MP_EQ, "decode 33142312");
287+
288+
mp_clear_multi(&int0, &int1, &int2, &int3, &int4, &int5, &int6, NULL);
284289
}
285290

286291
void test_eth_abi_bytes8() {

0 commit comments

Comments
 (0)