From bc045fc7b082b426d7fc165fd07f8184ba2c7ef2 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Thu, 3 Oct 2024 13:09:43 -0600 Subject: lib9p: Allow specifying a maximum value for an atom in *.txt --- lib9p/9p.gen | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'lib9p/9p.gen') 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{re_membername})\\*\\()?(?P{re_membername})\\[(?P.*)\\]\\)?" + f"(?:(?P{re_membername})\\*\\()?(?P{re_membername})\\[(?P[^,]*)(?:,max=(?P[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 -- cgit v1.2.3-2-g168b