summaryrefslogtreecommitdiff
path: root/lib9p
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p')
-rwxr-xr-xlib9p/9p.gen37
-rw-r--r--lib9p/9p.generated.c21
-rw-r--r--lib9p/include/lib9p/9p.generated.h1
3 files changed, 49 insertions, 10 deletions
diff --git a/lib9p/9p.gen b/lib9p/9p.gen
index 6e01b17..6f2ad2c 100755
--- a/lib9p/9p.gen
+++ b/lib9p/9p.gen
@@ -101,9 +101,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>[^,]*)(?:,max=(?P<max>[0-9]+))?\\]\\)?"
-)
+re_memberspec = f"(?:(?P<cnt>{re_membername})\\*\\()?(?P<name>{re_membername})\\[(?P<typ>[^,]*)(?:,max=(?P<max>[0-9]+))?\\]\\)?"
def parse_members(
@@ -138,7 +136,9 @@ def parse_members(
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")
+ raise ValueError(
+ f"',max=' may only be specified on a non-repeated atom"
+ )
member.max = int(maxstr)
ret += [member]
@@ -431,6 +431,8 @@ enum {idprefix}version {{
ret += "\n"
ret += c_typename(idprefix, struct) + " {\n"
for member in struct.members:
+ if struct.name == "stat" and member.name == "stat_size": # SPECIAL
+ continue
ret += f"\t{c_typename(idprefix, member.typ).ljust(typewidth)} {'*' if member.cnt else ' '}{member.name};"
if (not all_the_same) and (comment := c_vercomment(member.ver)):
ret += (" " * (namewidth - len(member.name))) + " " + comment
@@ -655,6 +657,9 @@ static ALWAYS_INLINE bool _validate_list(struct _validate_ctx *ctx,
ret += "}\n"
continue
+ if typ.name == "stat": # SPECIAL
+ ret += f"\n\tuint32_t size_offset = ctx->net_offset;"
+
prefix0 = "\treturn "
prefix1 = "\t || "
prefix2 = "\t "
@@ -673,6 +678,7 @@ static ALWAYS_INLINE bool _validate_list(struct _validate_ctx *ctx,
else:
ret += f"validate_{member.typ.name}(ctx)"
if member.max:
+ assert member.static_size
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}))"
@@ -681,6 +687,11 @@ static ALWAYS_INLINE bool _validate_list(struct _validate_ctx *ctx,
ret += " )"
prefix = prefix1
prev_size = member.static_size
+ if typ.name == "stat": # SPECIAL
+ assert typ.members[0].static_size
+ ret += f"\n{prefix1}((uint32_t)decode_u{typ.members[0].static_size*8}le(&ctx->net_bytes[size_offset]) != ctx->net_offset - size_offset)"
+ ret += f'\n{prefix2}\t? lib9p_error(ctx->ctx, LINUX_EBADMSG, "stat size does not match stat contents")"'
+ ret += f"\n{prefix2}\t: false)"
ret += ";\n"
ret += "}\n"
@@ -726,6 +737,9 @@ static ALWAYS_INLINE void unmarshal_8(struct _unmarshal_ctx *ctx, uint64_t *out)
if typ.members:
struct_versions = typ.members[0].ver
for member in typ.members:
+ if typ.name == "stat" and member.name == "stat_size": # SPECIAL
+ ret += f"\tsize->net_offset += {member.static_size};\n"
+ continue
ret += "\t"
prefix = "\t"
if member.ver != struct_versions:
@@ -809,6 +823,9 @@ static ALWAYS_INLINE bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val) {
ret += "}\n"
continue
+ if typ.name == "stat": # SPECIAL
+ ret += "\n\tuint32_t size_offset = ctx->net_offset;"
+
prefix0 = "\treturn "
prefix1 = "\t || "
prefix2 = "\t "
@@ -816,6 +833,12 @@ static ALWAYS_INLINE bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val) {
struct_versions = typ.members[0].ver
prefix = prefix0
for member in typ.members:
+ if typ.name == "stat" and member.name == "stat_size": # SPECIAL:
+ assert member.static_size
+ ret += f"\n{prefix }((ctx->net_offset + {member.static_size} > ctx->ctx->max_msg_size)"
+ ret += f"\n{prefix2}\t? _marshal_too_large(ctx)"
+ ret += f"\n{prefix2}\t: ({{ ctx->net_offset += {member.static_size}; false; }}))"
+ continue
ret += f"\n{prefix}"
if member.ver != struct_versions:
ret += "( " + c_vercond(idprefix, member.ver) + " && "
@@ -831,6 +854,12 @@ static ALWAYS_INLINE bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val) {
if member.ver != struct_versions:
ret += " )"
prefix = prefix1
+ if typ.name == "stat": # SPECIAL
+ assert typ.members[0].static_size
+ ret += f"\n{prefix1}((ctx->net_offset - size_offset > UINT16_MAX)"
+ ret += f'\n{prefix2}\t? lib9p_error(ctx->ctx, LINUX_ERANGE, "stat object too large")'
+ ret += f"\n{prefix2}\t: ({{ encode_u{typ.members[0].static_size*8}le((uint{typ.members[0].static_size*8}_t)(ctx->net_offset - size_offset), &ctx->net_bytes[size_offset]);"
+ ret += f"\n{prefix2} false; }}))"
ret += ";\n"
ret += "}\n"
diff --git a/lib9p/9p.generated.c b/lib9p/9p.generated.c
index 0259e23..4ec5ae5 100644
--- a/lib9p/9p.generated.c
+++ b/lib9p/9p.generated.c
@@ -383,6 +383,7 @@ static ALWAYS_INLINE bool validate_qid(struct _validate_ctx *ctx) {
}
static ALWAYS_INLINE bool validate_stat(struct _validate_ctx *ctx) {
+ uint32_t size_offset = ctx->net_offset;
return validate_2(ctx)
|| validate_2(ctx)
|| validate_4(ctx)
@@ -398,7 +399,10 @@ static ALWAYS_INLINE bool validate_stat(struct _validate_ctx *ctx) {
|| ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && validate_s(ctx) )
|| ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && validate_4(ctx) )
|| ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && validate_4(ctx) )
- || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && validate_4(ctx) );
+ || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && validate_4(ctx) )
+ || ((uint32_t)decode_u16le(&ctx->net_bytes[size_offset]) != ctx->net_offset - size_offset)
+ ? lib9p_error(ctx->ctx, LINUX_EBADMSG, "stat size does not match stat contents")"
+ : false);
}
static ALWAYS_INLINE bool validate_o(struct _validate_ctx *ctx) {
@@ -638,7 +642,7 @@ static ALWAYS_INLINE void unmarshal_qid(struct _unmarshal_ctx *ctx, struct lib9p
static ALWAYS_INLINE void unmarshal_stat(struct _unmarshal_ctx *ctx, struct lib9p_stat *out) {
memset(out, 0, sizeof(*out));
- unmarshal_2(ctx, &out->stat_size);
+ size->net_offset += 2;
unmarshal_2(ctx, &out->kern_type);
unmarshal_4(ctx, &out->kern_dev);
unmarshal_qid(ctx, &out->file_qid);
@@ -938,8 +942,11 @@ static ALWAYS_INLINE bool marshal_qid(struct _marshal_ctx *ctx, struct lib9p_qid
}
static ALWAYS_INLINE bool marshal_stat(struct _marshal_ctx *ctx, struct lib9p_stat *val) {
- return marshal_2(ctx, &val->stat_size)
- || marshal_2(ctx, &val->kern_type)
+ uint32_t size_offset = ctx->net_offset;
+ return ((ctx->net_offset + 2 > ctx->ctx->max_msg_size)
+ ? _marshal_too_large(ctx)
+ : ({ ctx->net_offset += 2; false; }))
+ return marshal_2(ctx, &val->kern_type)
|| marshal_4(ctx, &val->kern_dev)
|| marshal_qid(ctx, &val->file_qid)
|| marshal_dm(ctx, &val->file_mode)
@@ -953,7 +960,11 @@ static ALWAYS_INLINE bool marshal_stat(struct _marshal_ctx *ctx, struct lib9p_st
|| ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && marshal_s(ctx, &val->file_extension) )
|| ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && marshal_4(ctx, &val->file_owner_n_uid) )
|| ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && marshal_4(ctx, &val->file_owner_n_gid) )
- || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && marshal_4(ctx, &val->file_last_modified_n_uid) );
+ || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && marshal_4(ctx, &val->file_last_modified_n_uid) )
+ || ((ctx->net_offset - size_offset > UINT16_MAX)
+ ? lib9p_error(ctx->ctx, LINUX_ERANGE, "stat object too large")
+ : ({ encode_u16le((uint16_t)(ctx->net_offset - size_offset), &ctx->net_bytes[size_offset]);
+ false; }));
}
static ALWAYS_INLINE bool marshal_o(struct _marshal_ctx *ctx, lib9p_o_t *val) {
diff --git a/lib9p/include/lib9p/9p.generated.h b/lib9p/include/lib9p/9p.generated.h
index c6aaee9..f093aa1 100644
--- a/lib9p/include/lib9p/9p.generated.h
+++ b/lib9p/include/lib9p/9p.generated.h
@@ -96,7 +96,6 @@ struct lib9p_qid {
};
struct lib9p_stat {
- uint16_t stat_size;
uint16_t kern_type;
uint32_t kern_dev;
struct lib9p_qid file_qid;