Skip to content

Commit

Permalink
Fix boundary check logic (lune-org#243)
Browse files Browse the repository at this point in the history
  • Loading branch information
qwreey committed Nov 9, 2024
1 parent 902f5f9 commit b503cc9
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 61 deletions.
14 changes: 9 additions & 5 deletions crates/lune-std-ffi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,28 @@ See [tests/ffi](../../tests/ffi/README.md)

## TODO

- Rewrite error messages
- CString
- Add buffer for owned data support
- Add math operation.
- Add buffer as owned data support
- Add math operation for numeric types

> Provide related methods: `CTypeInfo:add(target, from1, from2, ...)` and `:sub` `:mul` `:div` `:mod` `:pow` `:max` `:min` `:gt` `:lt`
> Luau cannot handle f64, i64 or i128, so we should provide math operation for it
- Add bit operation
- Add bit operation for box/ref

> Luau only supports 32bit bit operations
- Add wchar and wstring support

> For windows API
> For windows API support
- Add varargs support
- Array argument in cfn
- More box/ref methods
- writeString
- readString
- writeBase64
- readBase64

## Code structure

Expand Down
85 changes: 35 additions & 50 deletions crates/lune-std-ffi/src/data/ref_data/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,77 +16,62 @@ impl RefBounds {
Self { above, below }
}

#[inline]
pub fn is_unsized(&self) -> bool {
self.above == usize::MAX && self.below == usize::MAX
}

// Check boundary
#[inline]
pub fn check_boundary(&self, offset: isize) -> bool {
if self.is_unsized() {
return true;
}
let sign = offset.signum();
let offset_abs = offset.unsigned_abs();
if sign == -1 {
self.above >= offset_abs
} else if sign == 1 {
self.below >= offset_abs
} else {
// sign == 0
true
match offset.signum() {
-1 => self.above >= offset_abs,
1 => self.below >= offset_abs,
0 => true,
_ => unreachable!(),
}
}

// Check boundary with specific size
//
// -4 ∧ ────── Above = 4
// -3 │ (Case1)
// -2 │ ┌──── Offset = -2 : offset >= 0 || abs(offset) <= above
// -1 │ │
// 0 │ │ Size = 4
// 1 │ │ (Case2)
// 2 │ ∨ ─── End = 2 : end = offset + size;
// 3 │ end <= 0 || end <= below
// 4 ∨ ────── Below = 4
//
#[inline]
pub fn check_sized(&self, offset: isize, size: usize) -> bool {
if self.is_unsized() {
return true;
}
// (Case1) offset over above
if offset < 0 && self.above < offset.unsigned_abs() {
return true;
}
let end = offset + (size as isize) - 1;
let end_sign = end.signum();
let end_abs = end.unsigned_abs();
if end_sign == -1 {
self.above >= end_abs
} else if end_sign == 1 {
self.below >= end_abs
} else {
// sign == 0
true
return false;
}

// (Case2) end over below
let end = offset + (size as isize);
end <= 0 || self.below >= end.unsigned_abs()
}

// Calculate new boundaries from bounds and offset
// Calculate new boundaries with bounds and offset
// No boundary checking in here
#[inline]
pub fn offset(&self, offset: isize) -> Self {
let sign = offset.signum();
let offset_abs = offset.unsigned_abs();

let high: usize = if sign == -1 {
self.above - offset_abs
} else if sign == 1 {
self.above + offset_abs
} else {
self.above
};

let low: usize = if sign == -1 {
self.below + offset_abs
} else if sign == 1 {
self.below - offset_abs
} else {
self.below
};

Self {
above: high,
below: low,
above: match sign {
-1 => self.above - offset_abs,
1 => self.above + offset_abs,
0 => self.above,
_ => unreachable!(),
},
below: match sign {
-1 => self.below + offset_abs,
1 => self.below - offset_abs,
0 => self.below,
_ => unreachable!(),
},
}
}
}
Expand Down
15 changes: 10 additions & 5 deletions tests/ffi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,28 @@ gcc for library compiling (for external-\*)

**External tests**

- [x] [external_closure](./external_closure/init.luau)
- [x] [external_math](./external_math/init.luau)
- [x] [external_pointer](./external_pointer/init.luau)
- [x] [external_print](./external_print/init.luau)
- [x] [external_struct](./external_struct/init.luau)
- [x] [external_closure](./external_closure/init.luau)

**Luau-side**

- [x] [isInteger](./isInteger.luau)
- [x] [cast](./cast.luau)
- [x] [write_boundary](./write_boundary.luau)
- [x] [read_boundary](./read_boundary.luau)
- [x] [free](./free.luau)
- [x] [isInteger](./isInteger.luau)
- [x] [read_boundary](./read_boundary.luau)
- [x] [write_boundary](./write_boundary.luau)

**Pretty Print**

- [ ] [pretty_print](./pretty_print)
- [x] [arr](./pretty_print/arr.luau)
- [ ] [box](./pretty_print/box.luau)
- [x] [fn](./pretty_print/fn.luau)
- [x] [ptr](./pretty_print/ptr.luau)
- [x] [struct](./pretty_print/struct.luau)
- [x] [type](./pretty_print/type.luau)

## Benchmark Results

Expand Down
2 changes: 1 addition & 1 deletion tests/ffi/readBoundary.luau
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ ok = pcall(function()
local box = ffi.box(ffi.u8.size * 2):ref(ffi.u16.size)
ffi.u16:readData(box)
end)
assert(ok, "assersion failed, Case7 should fail")
assert(not ok, "assersion failed, Case7 should fail")

0 comments on commit b503cc9

Please sign in to comment.