mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24:32 -08:00
[kernel] Add new zero_ok flag to syscall params
The new zero_ok flag is similar to optional for reference parameters, but only in cases where there is a length parameter. If that parameter is a reference parameter itself and is null, or it is non-null and contains a non-zero length, or there is no length parameter, then the main parameter may not be null.
This commit is contained in:
@@ -22,7 +22,7 @@ object endpoint : object {
|
||||
# is available.
|
||||
method receive [cap:receive] {
|
||||
param tag uint64 [out]
|
||||
param data buffer [out optional]
|
||||
param data buffer [out zero_ok]
|
||||
param timeout uint64 # Receive timeout in nanoseconds
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ object endpoint : object {
|
||||
# operation.
|
||||
method sendrecv [cap:send cap:receive] {
|
||||
param tag uint64 [inout]
|
||||
param data buffer [inout]
|
||||
param data buffer [inout zero_ok]
|
||||
param timeout uint64 # Receive timeout in nanoseconds
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,5 +62,7 @@ class Param:
|
||||
|
||||
@property
|
||||
def optional(self):
|
||||
return "optional" in self.options
|
||||
if "zero_ok" in self.options: return "zero_ok"
|
||||
elif "optional" in self.options: return "optional"
|
||||
else: return "required"
|
||||
|
||||
|
||||
@@ -22,11 +22,34 @@ for obj in syscalls.exposes:
|
||||
//[[[end]]]
|
||||
|
||||
namespace {
|
||||
enum class req { required, optional, zero_ok };
|
||||
|
||||
template <typename T>
|
||||
__attribute__((always_inline))
|
||||
inline bool check_refparam(const T* param, bool optional) {
|
||||
return reinterpret_cast<uintptr_t>(param) < arch::kernel_offset &&
|
||||
(optional || param);
|
||||
inline bool range_check(const T* param) {
|
||||
return reinterpret_cast<uintptr_t>(param) < arch::kernel_offset;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__((always_inline))
|
||||
inline bool check_refparam(const T* param, req required) {
|
||||
return range_check(param) && ((required == req::optional) || param);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__((always_inline))
|
||||
inline bool check_refparam(const T* param, size_t len, req required) {
|
||||
bool nullok = (required == req::optional) || (required == req::zero_ok && !len);
|
||||
return range_check(param) && (param || nullok);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__((always_inline))
|
||||
inline bool check_refparam(const T* param, size_t *len, req required) {
|
||||
if (!range_check(len)) return false;
|
||||
if (len) return check_refparam(param, *len, required);
|
||||
// if len is null but param is not, call that invalid.
|
||||
else return !param && required == req::optional;
|
||||
}
|
||||
|
||||
// When called with more than 6 arguments, the 7th argument to the
|
||||
@@ -67,7 +90,7 @@ for id, scope, method in syscalls.methods:
|
||||
argdefs.append(("j6_handle_t *", "self"))
|
||||
cxxargdefs.append("j6_handle_t *self")
|
||||
args.append("self")
|
||||
refparams.append(("self", False))
|
||||
refparams.append(("self", "required"))
|
||||
|
||||
elif not method.static:
|
||||
argdefs.append(("j6_handle_t", "self"))
|
||||
@@ -104,10 +127,9 @@ for id, scope, method in syscalls.methods:
|
||||
|
||||
if param.refparam:
|
||||
subs = param.type.c_names(param.options)
|
||||
refparams.append((param.name + subs[0][1], param.optional))
|
||||
if param.outparam:
|
||||
for sub in subs[1:]:
|
||||
refparams.append((param.name + sub[1], param.optional))
|
||||
checkargs = map(lambda x: f"{param.name}{x[1]}", subs)
|
||||
|
||||
refparams.append((", ".join(checkargs), param.optional))
|
||||
|
||||
first_args = ", ".join(map(lambda x: f"{x[0]} {x[1]}", argdefs[:6]))
|
||||
extra_argdefs = argdefs[6:]
|
||||
@@ -124,8 +146,8 @@ for id, scope, method in syscalls.methods:
|
||||
if extra_argdefs:
|
||||
cog.outl()
|
||||
|
||||
for pname, optional in refparams:
|
||||
cog.outl(f" if (!check_refparam({pname}, {cbool[optional]}))")
|
||||
for checkargs, optional in refparams:
|
||||
cog.outl(f" if (!check_refparam({checkargs}, req::{optional}))")
|
||||
cog.outl( " return j6_err_invalid_arg;")
|
||||
cog.outl()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user