summaryrefslogtreecommitdiff
path: root/lib9p/9p.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/9p.c')
-rw-r--r--lib9p/9p.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/lib9p/9p.c b/lib9p/9p.c
index 90a2b0d..e1303bd 100644
--- a/lib9p/9p.c
+++ b/lib9p/9p.c
@@ -45,9 +45,9 @@ int lib9p_errorf(struct lib9p_ctx *ctx, uint32_t linux_errno, char const *fmt, .
return -1;
}
-ssize_t lib9p_unmarshal_size(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
+ssize_t lib9p_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
/* Header */
- struct _checksize_ctx subctx = {
+ struct _validate_ctx subctx = {
.ctx = ctx,
.net_size = decode_u32le(net_bytes),
.net_bytes = net_bytes,
@@ -61,13 +61,21 @@ ssize_t lib9p_unmarshal_size(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
/* Body */
struct _vtable_msg vtable = _lib9p_vtables[ctx->version].msgs[typ];
- if (!vtable.unmarshal_extrasize)
+ if (!vtable.validate)
return lib9p_errorf(ctx, LINUX_EOPNOTSUPP, "unknown message type %s",
lib9p_msg_type_str(typ));
- if (vtable.unmarshal_extrasize(&subctx))
+ if (vtable.validate(&subctx))
return -1;
+ assert(subctx.net_offset <= subctx.net_size);
+ if (subctx.net_offset < subctx.net_size)
+ return lib9p_error(ctx, LINUX_EBADMSG, "message has %"PRIu32" extra bytes",
+ subctx.net_size - subctx.net_offset);
- return (ssize_t)(vtable.unmarshal_basesize + subctx.host_extra);
+ ssize_t ret;
+ if (__builtin_add_overflow(vtable.basesize, subctx.host_extra, &ret))
+ return lib9p_error(ctx, LINUX_EMSGSIZE, "unmarshalled payload overflows SSIZE_MAX");
+
+ return ret;
}
void lib9p_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
@@ -98,7 +106,7 @@ bool lib9p_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, uint16_t tag,
};
ret_bytes[4] = typ;
encode_u16le(tag, &ret_bytes[5]);
-
+
/* Body */
struct _vtable_msg vtable = _lib9p_vtables[ctx->version].msgs[typ];
if (vtable.marshal(&subctx, body))