summaryrefslogtreecommitdiff
path: root/lib9p
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-10-03 13:09:43 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-10-03 13:09:43 -0600
commitbc045fc7b082b426d7fc165fd07f8184ba2c7ef2 (patch)
tree79c06e18221e768f2b120599bcef5f4158ea5077 /lib9p
parentf401359d87f3375efdd39801652cc18574240049 (diff)
lib9p: Allow specifying a maximum value for an atom in *.txt
Diffstat (limited to 'lib9p')
-rw-r--r--lib9p/9P2000.txt4
-rwxr-xr-xlib9p/9p.gen26
-rw-r--r--lib9p/9p.generated.c21
3 files changed, 30 insertions, 21 deletions
diff --git a/lib9p/9P2000.txt b/lib9p/9P2000.txt
index fa04fe0..9cdb943 100644
--- a/lib9p/9P2000.txt
+++ b/lib9p/9P2000.txt
@@ -133,8 +133,8 @@ bitfield o 8
107/Rerror = "ename[s]"
108/Tflush = "oldtag[2]"
109/Rflush = ""
-110/Twalk = "fid[4] newfid[4] nwname[2] nwname*(wname[s])" # nwname has a maximum of 16
-111/Rwalk = "nwqid[2] nwqid*(wqid[qid])" # nwname has a maximum of 16
+110/Twalk = "fid[4] newfid[4] nwname[2,max=16] nwname*(wname[s])"
+111/Rwalk = "nwqid[2,max=16] nwqid*(wqid[qid])"
112/Topen = "fid[4] mode[o]"
113/Ropen = "qid[qid] iounit[4]"
114/Tcreate = "fid[4] name[s] perm[dm] mode[o]"
diff --git a/lib9p/9p.gen b/lib9p/9p.gen
index f974dd1..6e01b17 100755
--- a/lib9p/9p.gen
+++ b/lib9p/9p.gen
@@ -90,6 +90,7 @@ class Member:
cnt: str | None = None
name: str
typ: Atom | Bitfield | Struct
+ max: int | None = None
ver: set[str]
@property
@@ -101,7 +102,7 @@ class Member:
re_membername = "(?:[a-zA-Z_][a-zA-Z_0-9]*)"
re_memberspec = (
- f"(?:(?P<cnt>{re_membername})\\*\\()?(?P<name>{re_membername})\\[(?P<typ>.*)\\]\\)?"
+ f"(?:(?P<cnt>{re_membername})\\*\\()?(?P<name>{re_membername})\\[(?P<typ>[^,]*)(?:,max=(?P<max>[0-9]+))?\\]\\)?"
)
@@ -135,6 +136,11 @@ def parse_members(
raise ValueError(f"list count must be an integer type: {repr(cnt)}")
member.cnt = cnt
+ if maxstr := m.group("max"):
+ if (not isinstance(member.typ, Atom)) or member.cnt:
+ raise ValueError(f"',max=' may only be specified on a non-repeated atom")
+ member.max = int(maxstr)
+
ret += [member]
return ret
@@ -549,11 +555,8 @@ static ALWAYS_INLINE bool _validate_size_host(struct _validate_ctx *ctx, size_t
}
static ALWAYS_INLINE bool _validate_list(struct _validate_ctx *ctx,
- size_t cnt, size_t max,
+ size_t cnt,
_validate_fn_t item_fn, size_t item_host_size) {
- if (max && cnt > max)
- return lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "list size is too large (%zu > %zu)",
- cnt, max);
for (size_t i = 0; i < cnt; i++)
if (_validate_size_host(ctx, item_host_size) || item_fn(ctx))
return true;
@@ -654,6 +657,7 @@ static ALWAYS_INLINE bool _validate_list(struct _validate_ctx *ctx,
prefix0 = "\treturn "
prefix1 = "\t || "
+ prefix2 = "\t "
struct_versions = typ.members[0].ver
@@ -665,14 +669,14 @@ static ALWAYS_INLINE bool _validate_list(struct _validate_ctx *ctx,
ret += "( " + c_vercond(idprefix, member.ver) + " && "
if member.cnt is not None:
assert prev_size
- maxelem = 0
- if (
- typ.name in ["Twalk", "Rwalk"] and member.name[:1] == "w"
- ): # SPECIAL
- maxelem = 16
- ret += f"_validate_list(ctx, decode_u{prev_size*8}le(&ctx->net_bytes[ctx->net_offset-{prev_size}]), {maxelem}, validate_{member.typ.name}, sizeof({c_typename(idprefix, member.typ)}))"
+ ret += f"_validate_list(ctx, decode_u{prev_size*8}le(&ctx->net_bytes[ctx->net_offset-{prev_size}]), validate_{member.typ.name}, sizeof({c_typename(idprefix, member.typ)}))"
else:
ret += f"validate_{member.typ.name}(ctx)"
+ if member.max:
+ ret += f"\n{prefix1}(decode_u{member.static_size*8}le(&ctx->net_bytes[ctx->net_offset-{member.static_size}]) > ({c_typename(idprefix, member.typ)})({member.max})"
+ ret += f'\n{prefix2}\t? lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "list size is too large (%"PRIu{member.static_size*8}" > %"PRIu{member.static_size*8}")",'
+ ret += f"\n{prefix2}\t\tdecode_u{member.static_size*8}le(&ctx->net_bytes[ctx->net_offset-{member.static_size}]), ({c_typename(idprefix, member.typ)})({member.max}))"
+ ret += f"\n{prefix2}\t: false)"
if member.ver != struct_versions:
ret += " )"
prefix = prefix1
diff --git a/lib9p/9p.generated.c b/lib9p/9p.generated.c
index 387af79..0259e23 100644
--- a/lib9p/9p.generated.c
+++ b/lib9p/9p.generated.c
@@ -311,11 +311,8 @@ static ALWAYS_INLINE bool _validate_size_host(struct _validate_ctx *ctx, size_t
}
static ALWAYS_INLINE bool _validate_list(struct _validate_ctx *ctx,
- size_t cnt, size_t max,
+ size_t cnt,
_validate_fn_t item_fn, size_t item_host_size) {
- if (max && cnt > max)
- return lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "list size is too large (%zu > %zu)",
- cnt, max);
for (size_t i = 0; i < cnt; i++)
if (_validate_size_host(ctx, item_host_size) || item_fn(ctx))
return true;
@@ -464,12 +461,20 @@ static FLATTEN bool validate_Twalk(struct _validate_ctx *ctx) {
return validate_4(ctx)
|| validate_4(ctx)
|| validate_2(ctx)
- || _validate_list(ctx, decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), 16, validate_s, sizeof(struct lib9p_s));
+ || (decode_u16le(&ctx->net_bytes[ctx->net_offset-2]) > (uint16_t)(16)
+ ? lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "list size is too large (%"PRIu16" > %"PRIu16")",
+ decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), (uint16_t)(16))
+ : false)
+ || _validate_list(ctx, decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), validate_s, sizeof(struct lib9p_s));
}
static FLATTEN bool validate_Rwalk(struct _validate_ctx *ctx) {
return validate_2(ctx)
- || _validate_list(ctx, decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), 16, validate_qid, sizeof(struct lib9p_qid));
+ || (decode_u16le(&ctx->net_bytes[ctx->net_offset-2]) > (uint16_t)(16)
+ ? lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "list size is too large (%"PRIu16" > %"PRIu16")",
+ decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), (uint16_t)(16))
+ : false)
+ || _validate_list(ctx, decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), validate_qid, sizeof(struct lib9p_qid));
}
static FLATTEN bool validate_Topen(struct _validate_ctx *ctx) {
@@ -558,7 +563,7 @@ static FLATTEN bool validate_Rsession(struct _validate_ctx *UNUSED(ctx)) {
static FLATTEN bool validate_Tsread(struct _validate_ctx *ctx) {
return validate_4(ctx)
|| validate_2(ctx)
- || _validate_list(ctx, decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), 0, validate_s, sizeof(struct lib9p_s));
+ || _validate_list(ctx, decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), validate_s, sizeof(struct lib9p_s));
}
static FLATTEN bool validate_Rsread(struct _validate_ctx *ctx) {
@@ -568,7 +573,7 @@ static FLATTEN bool validate_Rsread(struct _validate_ctx *ctx) {
static FLATTEN bool validate_Tswrite(struct _validate_ctx *ctx) {
return validate_4(ctx)
|| validate_2(ctx)
- || _validate_list(ctx, decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), 0, validate_s, sizeof(struct lib9p_s))
+ || _validate_list(ctx, decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), validate_s, sizeof(struct lib9p_s))
|| validate_d(ctx);
}