Closed Shiranuit closed 1 year ago
Oh wow, this is an amazing PR. Thank you so much investigating, fixing, and then writing things up!
One thing which concerns here is that the table having the wrong size shouldn't cause the subsequent SETLIST
instruction to fail. I think we should probably also change presize
to use the underlying resize
function (which is what PUC Lua does). I think this patch looks reasonable:
--- a/src/main/java/org/squiddev/cobalt/LuaTable.java
+++ b/src/main/java/org/squiddev/cobalt/LuaTable.java
@@ -186,7 +186,7 @@ public final class LuaTable extends LuaValue {
*/
public void presize(int nArray) {
if (nArray > array.length) {
- array = setArrayVector(array, 1 << log2(nArray), false, weakValues);
+ resize(getHashLength(), 1 << log2(nArray), false);
}
}
@SquidDev
One thing which concerns here is that the table having the wrong size shouldn't cause the subsequent
SETLIST
instruction to fail. I think we should probably also changepresize
to use the underlyingresize
function (which is what PUC Lua does). I think this patch looks reasonable:--- a/src/main/java/org/squiddev/cobalt/LuaTable.java +++ b/src/main/java/org/squiddev/cobalt/LuaTable.java @@ -186,7 +186,7 @@ public final class LuaTable extends LuaValue { */ public void presize(int nArray) { if (nArray > array.length) { - array = setArrayVector(array, 1 << log2(nArray), false, weakValues); + resize(getHashLength(), 1 << log2(nArray), false); } }
Yes, I agree it would be better to use resize instead of presize, it will lead to much less errors with the allocations.
Unfortunately in the case described earlier it wouldn't have made a difference, since SETLIST
did not fail but assumed that it had to realloc the array since the size given by NEWTABLE
was smaller than the size SETLIST
obtained, which had the effect to override the size that the parser wanted to allocate specifically for the array because the array is static (until an insertion/deletion occurs).
Sorry, by fail I meant "produce a malformed table", not error or anything!
I think we should probably apply both patches, as both NEWLIST
and presize
are broken in different ways :D.
What does this PR do ?
The
NEWTABLE
instruction had an issue where it was allocating the wrong amount of size for the array and nodes. The issue was parser was encoding array length and hash length using a floating point byte and theNEWTABLE
instruction only reading the value as a byte without decoding it.This caused some unexpected behaviour in some cases like the one bellow where Lua is stuck in the for loop because of
next
not behaving correctly.What happens is
SETLIST
instruction that presizes the array to18
normally nothing would happens here because 18 would be equal to the length of the array that would have been 18 and so no resize would happen, but since only 17 slots have been allocated, the presize is going to allocate the next power of 2 from 18 which is 32.next
to return the wrong value