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.
|
# is available.
|
||||||
method receive [cap:receive] {
|
method receive [cap:receive] {
|
||||||
param tag uint64 [out]
|
param tag uint64 [out]
|
||||||
param data buffer [out optional]
|
param data buffer [out zero_ok]
|
||||||
param timeout uint64 # Receive timeout in nanoseconds
|
param timeout uint64 # Receive timeout in nanoseconds
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ object endpoint : object {
|
|||||||
# operation.
|
# operation.
|
||||||
method sendrecv [cap:send cap:receive] {
|
method sendrecv [cap:send cap:receive] {
|
||||||
param tag uint64 [inout]
|
param tag uint64 [inout]
|
||||||
param data buffer [inout]
|
param data buffer [inout zero_ok]
|
||||||
param timeout uint64 # Receive timeout in nanoseconds
|
param timeout uint64 # Receive timeout in nanoseconds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,5 +62,7 @@ class Param:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def optional(self):
|
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]]]
|
//[[[end]]]
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
enum class req { required, optional, zero_ok };
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
inline bool check_refparam(const T* param, bool optional) {
|
inline bool range_check(const T* param) {
|
||||||
return reinterpret_cast<uintptr_t>(param) < arch::kernel_offset &&
|
return reinterpret_cast<uintptr_t>(param) < arch::kernel_offset;
|
||||||
(optional || param);
|
}
|
||||||
|
|
||||||
|
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
|
// 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"))
|
argdefs.append(("j6_handle_t *", "self"))
|
||||||
cxxargdefs.append("j6_handle_t *self")
|
cxxargdefs.append("j6_handle_t *self")
|
||||||
args.append("self")
|
args.append("self")
|
||||||
refparams.append(("self", False))
|
refparams.append(("self", "required"))
|
||||||
|
|
||||||
elif not method.static:
|
elif not method.static:
|
||||||
argdefs.append(("j6_handle_t", "self"))
|
argdefs.append(("j6_handle_t", "self"))
|
||||||
@@ -104,10 +127,9 @@ for id, scope, method in syscalls.methods:
|
|||||||
|
|
||||||
if param.refparam:
|
if param.refparam:
|
||||||
subs = param.type.c_names(param.options)
|
subs = param.type.c_names(param.options)
|
||||||
refparams.append((param.name + subs[0][1], param.optional))
|
checkargs = map(lambda x: f"{param.name}{x[1]}", subs)
|
||||||
if param.outparam:
|
|
||||||
for sub in subs[1:]:
|
refparams.append((", ".join(checkargs), param.optional))
|
||||||
refparams.append((param.name + sub[1], param.optional))
|
|
||||||
|
|
||||||
first_args = ", ".join(map(lambda x: f"{x[0]} {x[1]}", argdefs[:6]))
|
first_args = ", ".join(map(lambda x: f"{x[0]} {x[1]}", argdefs[:6]))
|
||||||
extra_argdefs = argdefs[6:]
|
extra_argdefs = argdefs[6:]
|
||||||
@@ -124,8 +146,8 @@ for id, scope, method in syscalls.methods:
|
|||||||
if extra_argdefs:
|
if extra_argdefs:
|
||||||
cog.outl()
|
cog.outl()
|
||||||
|
|
||||||
for pname, optional in refparams:
|
for checkargs, optional in refparams:
|
||||||
cog.outl(f" if (!check_refparam({pname}, {cbool[optional]}))")
|
cog.outl(f" if (!check_refparam({checkargs}, req::{optional}))")
|
||||||
cog.outl( " return j6_err_invalid_arg;")
|
cog.outl( " return j6_err_invalid_arg;")
|
||||||
cog.outl()
|
cog.outl()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user