diff --git a/src/xrpld/app/misc/WasmHostFunc.h b/src/xrpld/app/misc/WasmHostFunc.h index 1d1f4d011b..86eb174451 100644 --- a/src/xrpld/app/misc/WasmHostFunc.h +++ b/src/xrpld/app/misc/WasmHostFunc.h @@ -29,22 +29,26 @@ namespace ripple { -int32_t const HF_ERR_INTERNAL = -1; -int32_t const HF_ERR_FIELD_NOT_FOUND = -2; -int32_t const HF_ERR_BUFFER_TOO_SMALL = -3; -int32_t const HF_ERR_NO_ARRAY = -4; -int32_t const HF_ERR_NOT_LEAF_FIELD = -5; -int32_t const HF_ERR_LOCATOR_MALFORMED = -6; -int32_t const HF_ERR_SLOT_OUT_RANGE = -7; -int32_t const HF_ERR_SLOTS_FULL = -8; -int32_t const HF_ERR_INVALID_SLOT = -9; -int32_t const HF_ERR_LEDGER_OBJ_NOT_FOUND = -10; -int32_t const HF_ERR_DECODING = -11; -int32_t const HF_ERR_DATA_FIELD_TOO_LARGE = -12; -int32_t const HF_ERR_OUT_OF_BOUNDS = -13; -int32_t const HF_ERR_NO_MEM_EXPORTED = -14; -int32_t const HF_ERR_INVALID_PARAMS = -15; -int32_t const HF_ERR_INVALID_ACCOUNT = -16; +enum HostFunctionErrors : int32_t { + HF_ERR_INTERNAL = -1, + HF_ERR_FIELD_NOT_FOUND = -2, + HF_ERR_BUFFER_TOO_SMALL = -3, + HF_ERR_NO_ARRAY = -4, + HF_ERR_NOT_LEAF_FIELD = -5, + HF_ERR_LOCATOR_MALFORMED = -6, + HF_ERR_SLOT_OUT_RANGE = -7, + HF_ERR_SLOTS_FULL = -8, + HF_ERR_EMPTY_SLOT = -9, + HF_ERR_LEDGER_OBJ_NOT_FOUND = -10, + HF_ERR_DECODING = -11, + HF_ERR_DATA_FIELD_TOO_LARGE = -12, + HF_ERR_POINTER_OUT_OF_BOUNDS = -13, + HF_ERR_NO_MEM_EXPORTED = -14, + HF_ERR_INVALID_PARAMS = -15, + HF_ERR_INVALID_ACCOUNT = -16, + HF_ERR_INVALID_FIELD = -17, + HF_ERR_INDEX_OUT_OF_BOUNDS = -18, +}; struct HostFunctions { diff --git a/src/xrpld/app/misc/WasmHostFuncImpl.cpp b/src/xrpld/app/misc/WasmHostFuncImpl.cpp index 71236034af..7c804f376d 100644 --- a/src/xrpld/app/misc/WasmHostFuncImpl.cpp +++ b/src/xrpld/app/misc/WasmHostFuncImpl.cpp @@ -70,50 +70,57 @@ WasmHostFunctionsImpl::cacheLedgerObj(Keylet const& keylet, int32_t cacheIdx) return cache[cacheIdx] ? cacheIdx + 1 : HF_ERR_LEDGER_OBJ_NOT_FOUND; } -static Bytes -getAnyFieldData(STBase const& obj) +static Expected +getAnyFieldData(STBase const* obj) { // auto const& fname = obj.getFName(); - auto const stype = obj.getSType(); + if (!obj) + return Unexpected(HF_ERR_FIELD_NOT_FOUND); + + auto const stype = obj->getSType(); switch (stype) { case STI_UNKNOWN: case STI_NOTPRESENT: - return {}; + return Unexpected(HF_ERR_FIELD_NOT_FOUND); + break; + case STI_OBJECT: + case STI_ARRAY: + return Unexpected(HF_ERR_NOT_LEAF_FIELD); break; case STI_ACCOUNT: { - auto const& super(static_cast(obj)); - auto const& data = super.value(); - return {data.begin(), data.end()}; + auto const& super(static_cast(obj)); + auto const& data = super->value(); + return Bytes{data.begin(), data.end()}; } break; case STI_AMOUNT: { - auto const& super(static_cast(obj)); - int64_t const data = super.xrp().drops(); + auto const& super(static_cast(obj)); + int64_t const data = super->xrp().drops(); auto const* b = reinterpret_cast(&data); auto const* e = reinterpret_cast(&data + 1); - return {b, e}; + return Bytes{b, e}; } break; case STI_VL: { - auto const& super(static_cast(obj)); - auto const& data = super.value(); - return {data.begin(), data.end()}; + auto const& super(static_cast(obj)); + auto const& data = super->value(); + return Bytes{data.begin(), data.end()}; } break; case STI_UINT256: { - auto const& super(static_cast const&>(obj)); - auto const& data = super.value(); - return {data.begin(), data.end()}; + auto const& super(static_cast const*>(obj)); + auto const& data = super->value(); + return Bytes{data.begin(), data.end()}; } break; case STI_UINT32: { auto const& super( - static_cast const&>(obj)); - std::uint32_t const data = super.value(); + static_cast const*>(obj)); + std::uint32_t const data = super->value(); auto const* b = reinterpret_cast(&data); auto const* e = reinterpret_cast(&data + 1); - return {b, e}; + return Bytes{b, e}; } break; default: @@ -121,7 +128,7 @@ getAnyFieldData(STBase const& obj) } Serializer msg; - obj.add(msg); + obj->add(msg); return msg.getData(); } @@ -129,13 +136,7 @@ getAnyFieldData(STBase const& obj) Expected WasmHostFunctionsImpl::getTxField(SField const& fname) { - auto const* field = ctx.tx.peekAtPField(fname); - if (!field) - return Unexpected(HF_ERR_FIELD_NOT_FOUND); - if ((STI_OBJECT == field->getSType()) || (STI_ARRAY == field->getSType())) - return Unexpected(HF_ERR_NOT_LEAF_FIELD); - - return getAnyFieldData(*field); + return getAnyFieldData(ctx.tx.peekAtPField(fname)); } Expected @@ -144,14 +145,7 @@ WasmHostFunctionsImpl::getCurrentLedgerObjField(SField const& fname) auto const sle = ctx.view().read(leKey); if (!sle) return Unexpected(HF_ERR_LEDGER_OBJ_NOT_FOUND); - - auto const* field = sle->peekAtPField(fname); - if (!field) - return Unexpected(HF_ERR_FIELD_NOT_FOUND); - if ((STI_OBJECT == field->getSType()) || (STI_ARRAY == field->getSType())) - return Unexpected(HF_ERR_NOT_LEAF_FIELD); - - return getAnyFieldData(*field); + return getAnyFieldData(sle->peekAtPField(fname)); } Expected @@ -160,17 +154,16 @@ WasmHostFunctionsImpl::getLedgerObjField(int32_t cacheIdx, SField const& fname) --cacheIdx; if (cacheIdx < 0 || cacheIdx >= MAX_CACHE) return Unexpected(HF_ERR_SLOT_OUT_RANGE); - if (!cache[cacheIdx]) - return Unexpected(HF_ERR_INVALID_SLOT); + return Unexpected(HF_ERR_EMPTY_SLOT); + return getAnyFieldData(cache[cacheIdx]->peekAtPField(fname)); +} - auto const* field = cache[cacheIdx]->peekAtPField(fname); - if (!field) - return Unexpected(HF_ERR_FIELD_NOT_FOUND); - if ((STI_OBJECT == field->getSType()) || (STI_ARRAY == field->getSType())) - return Unexpected(HF_ERR_NOT_LEAF_FIELD); - - return getAnyFieldData(*field); +static inline bool +noField(STBase const* field) +{ + return !field || (STI_NOTPRESENT == field->getSType()) || + (STI_UNKNOWN == field->getSType()); } static Expected @@ -188,11 +181,11 @@ locateField(STObject const& obj, Slice const& loc) int32_t const c = l[0]; auto const it = m.find(c); if (it == m.end()) - return Unexpected(HF_ERR_LOCATOR_MALFORMED); - auto const& fname(*it->second); + return Unexpected(HF_ERR_INVALID_FIELD); + auto const& fname(*it->second); field = obj.peekAtPField(fname); - if (!field || (STI_NOTPRESENT == field->getSType())) + if (noField(field)) return Unexpected(HF_ERR_FIELD_NOT_FOUND); } @@ -204,7 +197,7 @@ locateField(STObject const& obj, Slice const& loc) { auto const* arr = static_cast(field); if (c >= arr->size()) - return Unexpected(HF_ERR_LOCATOR_MALFORMED); + return Unexpected(HF_ERR_INDEX_OUT_OF_BOUNDS); field = &(arr->operator[](c)); } else if (STI_OBJECT == field->getSType()) @@ -213,9 +206,9 @@ locateField(STObject const& obj, Slice const& loc) auto const it = m.find(c); if (it == m.end()) - return Unexpected(HF_ERR_LOCATOR_MALFORMED); - auto const& fname(*it->second); + return Unexpected(HF_ERR_INVALID_FIELD); + auto const& fname(*it->second); field = o->peekAtPField(fname); } else // simple field must be the last one @@ -223,7 +216,7 @@ locateField(STObject const& obj, Slice const& loc) return Unexpected(HF_ERR_LOCATOR_MALFORMED); } - if (!field || (STI_NOTPRESENT == field->getSType())) + if (noField(field)) return Unexpected(HF_ERR_FIELD_NOT_FOUND); } @@ -237,11 +230,7 @@ WasmHostFunctionsImpl::getTxNestedField(Slice const& locator) if (!r) return Unexpected(r.error()); - auto const* field = r.value(); - if ((STI_OBJECT == field->getSType()) || (STI_ARRAY == field->getSType())) - return Unexpected(HF_ERR_NOT_LEAF_FIELD); - - return getAnyFieldData(*field); + return getAnyFieldData(r.value()); } Expected @@ -255,11 +244,7 @@ WasmHostFunctionsImpl::getCurrentLedgerObjNestedField(Slice const& locator) if (!r) return Unexpected(r.error()); - auto const* field = r.value(); - if ((STI_OBJECT == field->getSType()) || (STI_ARRAY == field->getSType())) - return Unexpected(HF_ERR_NOT_LEAF_FIELD); - - return getAnyFieldData(*field); + return getAnyFieldData(r.value()); } Expected @@ -272,17 +257,13 @@ WasmHostFunctionsImpl::getLedgerObjNestedField( return Unexpected(HF_ERR_SLOT_OUT_RANGE); if (!cache[cacheIdx]) - return Unexpected(HF_ERR_INVALID_SLOT); + return Unexpected(HF_ERR_EMPTY_SLOT); auto const r = locateField(*cache[cacheIdx], locator); if (!r) return Unexpected(r.error()); - auto const* field = r.value(); - if ((STI_OBJECT == field->getSType()) || (STI_ARRAY == field->getSType())) - return Unexpected(HF_ERR_NOT_LEAF_FIELD); - - return getAnyFieldData(*field); + return getAnyFieldData(r.value()); } int32_t @@ -292,7 +273,7 @@ WasmHostFunctionsImpl::getTxArrayLen(SField const& fname) return HF_ERR_NO_ARRAY; auto const* field = ctx.tx.peekAtPField(fname); - if (!field) + if (noField(field)) return HF_ERR_FIELD_NOT_FOUND; if (field->getSType() != STI_ARRAY) @@ -313,7 +294,7 @@ WasmHostFunctionsImpl::getCurrentLedgerObjArrayLen(SField const& fname) return HF_ERR_LEDGER_OBJ_NOT_FOUND; auto const* field = sle->peekAtPField(fname); - if (!field) + if (noField(field)) return HF_ERR_FIELD_NOT_FOUND; if (field->getSType() != STI_ARRAY) @@ -335,10 +316,10 @@ WasmHostFunctionsImpl::getLedgerObjArrayLen( return HF_ERR_SLOT_OUT_RANGE; if (!cache[cacheIdx]) - return HF_ERR_INVALID_SLOT; + return HF_ERR_EMPTY_SLOT; auto const* field = cache[cacheIdx]->peekAtPField(fname); - if (!field) + if (noField(field)) return HF_ERR_FIELD_NOT_FOUND; if (field->getSType() != STI_ARRAY) @@ -354,8 +335,8 @@ WasmHostFunctionsImpl::getTxNestedArrayLen(Slice const& locator) auto const r = locateField(ctx.tx, locator); if (!r) return r.error(); - auto const* field = r.value(); + auto const* field = r.value(); if (field->getSType() != STI_ARRAY) return HF_ERR_NO_ARRAY; int32_t const sz = static_cast(field)->size(); @@ -372,8 +353,8 @@ WasmHostFunctionsImpl::getCurrentLedgerObjNestedArrayLen(Slice const& locator) auto const r = locateField(*sle, locator); if (!r) return r.error(); - auto const* field = r.value(); + auto const* field = r.value(); if (field->getSType() != STI_ARRAY) return HF_ERR_NO_ARRAY; int32_t const sz = static_cast(field)->size(); @@ -391,14 +372,13 @@ WasmHostFunctionsImpl::getLedgerObjNestedArrayLen( return HF_ERR_SLOT_OUT_RANGE; if (!cache[cacheIdx]) - return HF_ERR_INVALID_SLOT; + return HF_ERR_EMPTY_SLOT; auto const r = locateField(*cache[cacheIdx], locator); if (!r) return r.error(); auto const* field = r.value(); - if (field->getSType() != STI_ARRAY) return HF_ERR_NO_ARRAY; int32_t const sz = static_cast(field)->size(); @@ -439,7 +419,10 @@ WasmHostFunctionsImpl::credentialKeylet( AccountID const& issuer, Bytes const& credentialType) { - if (!subject || !issuer || credentialType.empty() || + if (!subject || !issuer) + return Unexpected(HF_ERR_INVALID_ACCOUNT); + + if (credentialType.empty() || credentialType.size() > maxCredentialTypeLength) return Unexpected(HF_ERR_INVALID_PARAMS); @@ -472,22 +455,19 @@ WasmHostFunctionsImpl::oracleKeylet( Expected WasmHostFunctionsImpl::getNFT(AccountID const& account, uint256 const& nftId) { - if (!account || !nftId) - { - getJournal().trace() << "WAMR getNFT: Invalid account or NFT ID"; + if (!account) + return Unexpected(HF_ERR_INVALID_ACCOUNT); + + if (!nftId) return Unexpected(HF_ERR_INVALID_PARAMS); - } auto obj = nft::findToken(ctx.view(), account, nftId); if (!obj) - { - getJournal().trace() << "WAMR getNFT: NFT not found"; return Unexpected(HF_ERR_LEDGER_OBJ_NOT_FOUND); - } auto ouri = obj->at(~sfURI); if (!ouri) - return Bytes(); + return Unexpected(HF_ERR_FIELD_NOT_FOUND); Slice const s = ouri->value(); return Bytes(s.begin(), s.end()); diff --git a/src/xrpld/app/misc/WasmHostFuncWrapper.cpp b/src/xrpld/app/misc/WasmHostFuncWrapper.cpp index 9b5968c31d..0e1f886259 100644 --- a/src/xrpld/app/misc/WasmHostFuncWrapper.cpp +++ b/src/xrpld/app/misc/WasmHostFuncWrapper.cpp @@ -37,12 +37,15 @@ setData( if (!ssz) return 0; + if (dst < 0 || dsz < 0 || !src || ssz < 0) + return HF_ERR_INVALID_PARAMS; + auto mem = rt ? rt->getMem() : wmem(); if (!mem.s) return HF_ERR_NO_MEM_EXPORTED; if (dst + dsz > mem.s) - return HF_ERR_OUT_OF_BOUNDS; + return HF_ERR_POINTER_OUT_OF_BOUNDS; if (ssz > dsz) return HF_ERR_BUFFER_TOO_SMALL; @@ -54,7 +57,7 @@ setData( static Expected getData(InstanceWrapper const* rt, int32_t src, int32_t ssz) { - if (!ssz) + if (src < 0 || ssz <= 0) return Unexpected(HF_ERR_INVALID_PARAMS); auto mem = rt ? rt->getMem() : wmem(); @@ -62,7 +65,7 @@ getData(InstanceWrapper const* rt, int32_t src, int32_t ssz) return Unexpected(HF_ERR_NO_MEM_EXPORTED); if (src + ssz > mem.s) - return Unexpected(HF_ERR_OUT_OF_BOUNDS); + return Unexpected(HF_ERR_POINTER_OUT_OF_BOUNDS); Bytes data(mem.p + src, mem.p + src + ssz); return data; @@ -72,7 +75,7 @@ static Expected getDataAccount(InstanceWrapper const* rt, int32_t ptr, int32_t sz) { auto const r = getData(rt, ptr, sz); - if (!r || (r->size() < AccountID::bytes)) + if (!r || (r->size() != AccountID::bytes)) return Unexpected(HF_ERR_INVALID_PARAMS); return AccountID::fromVoid(r->data()); @@ -81,7 +84,7 @@ getDataAccount(InstanceWrapper const* rt, int32_t ptr, int32_t sz) static Expected getDataString(InstanceWrapper const* rt, int32_t src, int32_t ssz) { - if (!ssz) + if (src < 0 || ssz <= 0) return Unexpected(HF_ERR_INVALID_PARAMS); auto mem = rt ? rt->getMem() : wmem(); @@ -89,7 +92,7 @@ getDataString(InstanceWrapper const* rt, int32_t src, int32_t ssz) return Unexpected(HF_ERR_NO_MEM_EXPORTED); if (src + ssz > mem.s) - return Unexpected(HF_ERR_OUT_OF_BOUNDS); + return Unexpected(HF_ERR_POINTER_OUT_OF_BOUNDS); std::string data(mem.p + src, mem.p + src + ssz); return data; @@ -179,7 +182,7 @@ cacheLedgerObj_wrap( RET(r.error()); } - if (r->size() < uint256::bytes) + if (r->size() != uint256::bytes) { RET(HF_ERR_INVALID_PARAMS); } @@ -203,7 +206,7 @@ getTxField_wrap( auto const it = m.find(params->data[0].of.i32); if (it == m.end()) { - RET(HF_ERR_FIELD_NOT_FOUND); + RET(HF_ERR_INVALID_FIELD); } auto const& fname(*it->second); @@ -234,7 +237,7 @@ getCurrentLedgerObjField_wrap( auto const it = m.find(params->data[0].of.i32); if (it == m.end()) { - RET(HF_ERR_FIELD_NOT_FOUND); + RET(HF_ERR_INVALID_FIELD); } auto const& fname(*it->second); @@ -265,7 +268,7 @@ getLedgerObjField_wrap( auto const it = m.find(params->data[1].of.i32); if (it == m.end()) { - RET(HF_ERR_FIELD_NOT_FOUND); + RET(HF_ERR_INVALID_FIELD); } auto const& fname(*it->second); @@ -384,7 +387,7 @@ getTxArrayLen_wrap( auto const it = m.find(params->data[0].of.i32); if (it == m.end()) { - RET(HF_ERR_FIELD_NOT_FOUND); + RET(HF_ERR_INVALID_FIELD); } auto const& fname(*it->second); @@ -405,7 +408,7 @@ getCurrentLedgerObjArrayLen_wrap( auto const it = m.find(params->data[0].of.i32); if (it == m.end()) { - RET(HF_ERR_FIELD_NOT_FOUND); + RET(HF_ERR_INVALID_FIELD); } auto const& fname(*it->second); @@ -426,7 +429,7 @@ getLedgerObjArrayLen_wrap( auto const it = m.find(params->data[1].of.i32); if (it == m.end()) { - RET(HF_ERR_FIELD_NOT_FOUND); + RET(HF_ERR_INVALID_FIELD); } auto const& fname(*it->second);