Skip to content

Commit 11480e8

Browse files
author
Renato Maia
committed
fixup! Fix offset calculation for write operations in structs
1 parent bd85e1f commit 11480e8

File tree

2 files changed

+81
-10
lines changed

2 files changed

+81
-10
lines changed

lua/memory/layout.lua

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -182,14 +182,18 @@ function layout.struct(field, ...)
182182
end
183183
function spec.write(self, value, ...)
184184
if getmetatable(value) == Pointer then
185-
local src, dst = value.struct, spec
186-
assert(src.bitoff == 0 and src.bits%8 == 0
187-
and dst.bitoff == 0 and dst.bits%8 == 0, "unsupported")
188-
assert(dst.bytes == src.bytes, "size mismatch")
189-
local selfpos = rawget(self.parent, "pos")
190-
local valuepos = rawget(value.parent, "pos")
191-
memcopy(self.parent.buffer, value.parent.buffer,
192-
selfpos+dst.pos, selfpos+dst.pos+dst.bytes-1, valuepos+src.pos)
185+
local srcspec, dstspec = value.struct, spec
186+
if srcspec.bitoff == 0 and srcspec.bits%8 == 0 and
187+
dstspec.bitoff == 0 and dstspec.bits%8 == 0 then
188+
assert(dstspec.bytes == srcspec.bytes, "size mismatch")
189+
local srcptr, dstptr = value.parent, self.parent
190+
local dstpos = dstptr.pos+dstspec.pos-1
191+
local srcpos = srcptr.pos+srcspec.pos-1
192+
local len = dstspec.bytes
193+
memcopy(dstptr.buffer, srcptr.buffer, dstpos, dstpos+len-1, srcpos)
194+
else
195+
error("unsupported")
196+
end
193197
else
194198
error("unsupported")
195199
end
@@ -216,8 +220,8 @@ function module.newpointer(struct)
216220
end
217221

218222
function module.setpointer(pointer, buffer, pos)
219-
rawset(pointer, "buffer", buffer)
220-
rawset(pointer, "pos", pos or 1)
223+
pointer.buffer = buffer or empty
224+
pointer.pos = pos or 1
221225
end
222226

223227
return module

test/testlayout.lua

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,73 @@ do
350350

351351
memory.fill(m2, 0xff)
352352
p.nested = p2.nested ; assertbytes(m, 0x69, 0xaa, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xaa)
353+
354+
for _, size in ipairs{1,2,3,5,6} do
355+
local p3 = layout.newpointer(layout.newstruct{
356+
{ key = "nested", type = "struct", { bytes = size } },
357+
})
358+
local m3 = memory.create(size)
359+
layout.setpointer(p3, m3)
360+
asserterr("size mismatch", function () p3.nested = p.nested end)
361+
asserterr("size mismatch", function () p.nested = p3.nested end)
362+
end
363+
end
364+
365+
do
366+
local p = layout.newpointer(layout.newstruct{
367+
{ key = "half", bits = 4, endian = "big" },
368+
{ key = "nested", type = "struct",
369+
{ key = "half", bits = 4, endian = "big" },
370+
{ key = "many", bits = 14, endian = "big" },
371+
{ key = "one", bits = 1, endian = "big" },
372+
},
373+
{ key = "one", bits = 1, endian = "big" },
374+
})
375+
local m = memory.create(3)
376+
layout.setpointer(p, m)
377+
378+
memory.set(m, 1, 0x12, 0x34, 0x56)
379+
assert(p.half == 0x1)
380+
assert(p.nested.half == 0x2)
381+
assert(p.nested.many == 0x3454>>2)
382+
assert(p.nested.one == 0x1)
383+
assert(p.one == 0x0)
384+
385+
memory.fill(m, 0x55)
386+
p.half = 0xa ; assertbytes(m, 0xa5, 0x55, 0x55)
387+
p.nested.half = 0xb ; assertbytes(m, 0xab, 0x55, 0x55)
388+
p.nested.many = 0xcdec>>2 ; assertbytes(m, 0xab, 0xcd, 0xed)
389+
p.nested.one = 0x1 ; assertbytes(m, 0xab, 0xcd, 0xef)
390+
p.one = 0x1 ; assertbytes(m, 0xab, 0xcd, 0xef)
391+
392+
local p2 = layout.newpointer(layout.newstruct{
393+
{ bits = 7 },
394+
{ key = "nested", type = "struct", { bits = 9 } },
395+
})
396+
local m2 = memory.create(2)
397+
layout.setpointer(p2, m2)
398+
asserterr("unsupported", function () p2.nested = p.nested end)
399+
asserterr("unsupported", function () p.nested = p2.nested end)
400+
end
401+
402+
do
403+
local p = layout.newpointer(layout.newstruct{
404+
{ key = "one", bytes = 1 },
405+
{ key = "other", bytes = 1 },
406+
})
407+
local m = memory.create(6)
408+
memory.set(m, 1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05)
409+
layout.setpointer(p, m, 3)
410+
assert(p.one == 2)
411+
assert(p.other == 3)
412+
p.one = 252
413+
p.other = 253
414+
layout.setpointer(p, m, 5)
415+
assert(p.one == 4)
416+
assert(p.other == 5)
417+
p.one = 254
418+
p.other = 255
419+
assertbytes(m, 0x00, 0x01, 0xfc, 0xfd, 0xfe, 0xff)
353420
end
354421

355422
print("Success!")

0 commit comments

Comments
 (0)