diff --git a/doc/en/block-properties.md b/doc/en/block-properties.md index 011b1a77..a2435ec3 100644 --- a/doc/en/block-properties.md +++ b/doc/en/block-properties.md @@ -168,6 +168,6 @@ Available data types: | f64 | 8 bytes | floating-point 64 bits | | char | 1 byte | character | -Currently, the total sum of the field sizes cannot exceed 240 bytes. - -A character array can be used to store UTF-8 strings. +- Currently, the total sum of the field sizes cannot exceed 240 bytes. +- A field without an array length specification is equivalent to an array of 1 element. +- A character array can be used to store UTF-8 strings. diff --git a/doc/en/scripting/builtins/libblock.md b/doc/en/scripting/builtins/libblock.md index 82aba4e7..fdb4fa4d 100644 --- a/doc/en/scripting/builtins/libblock.md +++ b/doc/en/scripting/builtins/libblock.md @@ -138,6 +138,7 @@ The result will use the destination table instead of creating a new one if the o ```lua -- writes a value to the specified block field -- * throws an exception if the types are incompatible +-- * throws an exception when array is out of bounds -- * does nothing if the block does not have the field block.set_field( x: int, y: int, z: int, @@ -148,8 +149,9 @@ block.set_field( -- returns the value written to the block field -- * returns nil if: --- 1. the field does not exist --- 2. no writes were made to any block field +-- 1. the field does not exist +-- 2. no writes were made to any block field +-- * throws an exception when array is out of bounds block.get_field( x: int, y: int, z: int, name: str, diff --git a/doc/ru/block-properties.md b/doc/ru/block-properties.md index 8e4d7d5d..cb681300 100644 --- a/doc/ru/block-properties.md +++ b/doc/ru/block-properties.md @@ -171,6 +171,6 @@ | f64 | 8 байт | вещественный 64 бит | | char | 1 байт | символьный | -На данный момент общая сумма размеров полей не может превышать 240 байт. - -Массив символьного типа может использоваться для хранения UTF-8 строк. +- На данный момент общая сумма размеров полей не может превышать 240 байт. +- Поле без указания длины массива эквивалентно массиву из 1 элемента. +- Массив символьного типа может использоваться для хранения UTF-8 строк. diff --git a/doc/ru/scripting/builtins/libblock.md b/doc/ru/scripting/builtins/libblock.md index 0b4f5e35..e7746a37 100644 --- a/doc/ru/scripting/builtins/libblock.md +++ b/doc/ru/scripting/builtins/libblock.md @@ -165,6 +165,7 @@ block.get_textures(id: int) -> таблица строк ```lua -- записывает значение в указанное поле блока -- * бросает исключение при несовместимости типов +-- * бросает исключение при выходе за границы массива -- * ничего не делает при отсутствии поля у блока block.set_field( x: int, y: int, z: int, @@ -177,6 +178,7 @@ block.set_field( -- * возвращает nil если: -- 1. поле не существует -- 2. ни в одно поле блока не было произведено записи +-- * бросает исключение при выходе за границы массива block.get_field( x: int, y: int, z: int, name: str, diff --git a/src/data/StructLayout.cpp b/src/data/StructLayout.cpp index 91cae4f6..a7af3e91 100644 --- a/src/data/StructLayout.cpp +++ b/src/data/StructLayout.cpp @@ -372,6 +372,12 @@ void StructLayout::deserialize(const dv::value& src) { int elements = 1; fieldmap.at("length").get(elements); + if (elements <= 0) { + throw std::runtime_error( + "invalid field " + util::quote(name) + " length: " + + std::to_string(elements) + ); + } auto convertStrategy = FieldConvertStrategy::RESET; if (fieldmap.has("convert-strategy")) { diff --git a/src/logic/scripting/lua/libblock.cpp b/src/logic/scripting/lua/libblock.cpp index f186fdae..ab5febac 100644 --- a/src/logic/scripting/lua/libblock.cpp +++ b/src/logic/scripting/lua/libblock.cpp @@ -489,6 +489,10 @@ static int l_get_field(lua::State* L) { if (field == nullptr) { return 0; } + if (index >= field->elements) { + throw std::out_of_range( + "index out of bounds [0, "+std::to_string(field->elements)+"]"); + } const ubyte* src = chunk->blocksMetadata.find(voxelIndex); if (src == nullptr) { return 0; @@ -553,6 +557,10 @@ static int l_set_field(lua::State* L) { if (field == nullptr) { return 0; } + if (index >= field->elements) { + throw std::out_of_range( + "index out of bounds [0, "+std::to_string(field->elements)+"]"); + } ubyte* dst = chunk->blocksMetadata.find(voxelIndex); if (dst == nullptr) { dst = chunk->blocksMetadata.allocate(voxelIndex, dataStruct.size());