Skip to content

Commit

Permalink
Fix LuaTable.getFreePos failing on GCed keys
Browse files Browse the repository at this point in the history
We incorrectly strengthened the table key, which meant we didn't
distinguish between empty keys and GCed weak keys.

Fixes cc-tweaked/CC-Tweaked#1721
  • Loading branch information
SquidDev committed Feb 14, 2024
1 parent 0108797 commit bf20e88
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 4 deletions.
5 changes: 1 addition & 4 deletions src/main/java/org/squiddev/cobalt/LuaTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,7 @@ private void rehash(LuaValue extraKey, boolean mode) {
private int getFreePos() {
if (keys.length == 0) return -1;
while (lastFree >= 0) {
LuaValue last = key(lastFree--);
if (last == NIL) {
if (keys[lastFree--] == NIL) {
return lastFree + 1;
}
}
Expand Down Expand Up @@ -865,8 +864,6 @@ public void rawsetImpl(LuaValue key, LuaValue value) {
return;
}

// TODO: Check valid key here instead of at the call site!

do {
int node = getNode(key);
if (node == -1) node = newKey(key);
Expand Down
17 changes: 17 additions & 0 deletions src/test/java/org/squiddev/cobalt/table/TableHashTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -266,4 +266,21 @@ public void testShrink() {
for (int i = 0; i < 8; i++) t.rawset("new_key_" + i, Constants.TRUE);
assertEquals(8, TableOperations.getHashLength(t));
}

@Test
public void testWeakCanBeReplaced() throws LuaError {
var t = new LuaTable();

var mt = new LuaTable();
mt.rawset("__mode", ValueFactory.valueOf("k"));
t.setMetatable(null, mt);

for (int j = 0; j < 16; j++) {
for (int i = 0; i < 256; i++) t.rawset(new LuaTable(), Constants.TRUE);
System.gc();

int hash = TableOperations.getHashLength(t);
if (hash > 512) throw new AssertionError("Expected hash to be <=512, but is " + hash);
}
}
}

0 comments on commit bf20e88

Please sign in to comment.