diff options
-rw-r--r-- | lib9p/core_gen/c_validate.py | 2 | ||||
-rw-r--r-- | lib9p/core_generated.c | 12 | ||||
-rw-r--r-- | lib9p/core_include/lib9p/core.h | 12 | ||||
-rw-r--r-- | lib9p/srv_include/lib9p/srv.h | 2 | ||||
-rw-r--r-- | libmisc/include/libmisc/fmt.h | 31 | ||||
-rw-r--r-- | libmisc/tests/test_fmt.c | 9 |
6 files changed, 44 insertions, 24 deletions
diff --git a/lib9p/core_gen/c_validate.py b/lib9p/core_gen/c_validate.py index e7a4017..8997237 100644 --- a/lib9p/core_gen/c_validate.py +++ b/lib9p/core_gen/c_validate.py @@ -67,7 +67,7 @@ def gen_c_validate(versions: set[str], typs: list[idl.UserType]) -> str: "\t\tsize_t len = n;\n" "\t\tVALIDATE_NET_BYTES(len);\n" "\t\tif (!utf8_is_valid_without_nul(&net_bytes[net_offset-len], len))\n" - f'\t\t\treturn lib9p_error(ctx, {c9util.IDENT("ERRNO_L_EBADMSG")}, "message contains invalid UTF-8");\n' + f'\t\t\treturn lib9p_error(ctx, {c9util.IDENT("ERRNO_L_EILSEQ")}, "message contains invalid UTF-8");\n' "\t}\n" ) ret += cutil.macro( diff --git a/lib9p/core_generated.c b/lib9p/core_generated.c index 6e3633f..ad7b210 100644 --- a/lib9p/core_generated.c +++ b/lib9p/core_generated.c @@ -229,12 +229,12 @@ static const lib9p_lock_flags_t lock_flags_masks[LIB9P_VER_NUM] = { return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "message is too short for content"); \ if (net_offset > net_size) \ return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "message is too short for content (", net_offset, " > ", net_size, ")"); -#define VALIDATE_NET_UTF8(n) \ - { \ - size_t len = n; \ - VALIDATE_NET_BYTES(len); \ - if (!utf8_is_valid_without_nul(&net_bytes[net_offset-len], len)) \ - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "message contains invalid UTF-8"); \ +#define VALIDATE_NET_UTF8(n) \ + { \ + size_t len = n; \ + VALIDATE_NET_BYTES(len); \ + if (!utf8_is_valid_without_nul(&net_bytes[net_offset-len], len)) \ + return lib9p_error(ctx, LIB9P_ERRNO_L_EILSEQ, "message contains invalid UTF-8"); \ } #define RESERVE_HOST_BYTES(n) \ if (__builtin_add_overflow(host_size, n, &host_size)) \ diff --git a/lib9p/core_include/lib9p/core.h b/lib9p/core_include/lib9p/core.h index 4941220..afefa2b 100644 --- a/lib9p/core_include/lib9p/core.h +++ b/lib9p/core_include/lib9p/core.h @@ -98,11 +98,7 @@ void fmt_print_lib9p_msg(lo_interface fmt_dest w, struct lib9p_ctx *ctx, enum li * number may be larger than net_bytes due to (1) struct padding, (2) * array pointers. * - * Emits an error (return -1, set ctx->err_num and ctx->err_msg) if - * either the message type is unknown, or if net_bytes is too short - * for that message type, or if an invalid string (invalid UTF-8, - * contains a nul-byte) is encountered. - * + * @param ctx : negotiated protocol parameters, where to record errors * @param net_bytes : the complete request, starting with the "size[4]" * * @return required size, or -1 on error @@ -110,7 +106,7 @@ void fmt_print_lib9p_msg(lo_interface fmt_dest w, struct lib9p_ctx *ctx, enum li * @errno L_EOPNOTSUPP: message is an R-message * @errno L_EOPNOTSUPP: message has unknown type * @errno L_EBADMSG: message is wrong size for content - * @errno L_EBADMSG: message contains invalid UTF-8 + * @errno L_EILSEQ: message contains invalid UTF-8, or the UTF-8 contains a nul-byte * @errno L_EBADMSG: message contains a bitfield with unknown bits * @errno L_EMSGSIZE: would-be return value overflows SSIZE_MAX */ @@ -142,9 +138,9 @@ void lib9p_Tmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, * * @param ctx : negotiated protocol parameters, where to record errors * @param typ : the message type - * @param msg : the message to encode + * @param msg : the message to encode (`struct lib9p_msg_XXXX` according to `typ`) * - * @return ret_bytes : the buffer to encode to, must be at be at least ctx->max_msg_size bytes + * @return ret : the buffer to encode to * @return whether there was an error (false=success, true=error) * * @errno L_ERANGE: reply does not fit in ctx->max_msg_size diff --git a/lib9p/srv_include/lib9p/srv.h b/lib9p/srv_include/lib9p/srv.h index eb87d6f..89dc986 100644 --- a/lib9p/srv_include/lib9p/srv.h +++ b/lib9p/srv_include/lib9p/srv.h @@ -185,7 +185,7 @@ LO_INTERFACE(lib9p_srv_fio); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ LO_FUNC(void , iofree ) \ /** \ * Return the idx-th dirent. idx will always be either 0 or \ - * prev_idx+1. A dirrent with an empty name signals EOF. The string \ + * prev_idx+1. A dirent with an empty name signals EOF. The string \ * must remain valid until the next dread() call or iofree(). \ */ \ LO_FUNC(struct lib9p_srv_dirent , dread , struct lib9p_srv_ctx *, \ diff --git a/libmisc/include/libmisc/fmt.h b/libmisc/include/libmisc/fmt.h index c0743ff..6c04d99 100644 --- a/libmisc/include/libmisc/fmt.h +++ b/libmisc/include/libmisc/fmt.h @@ -9,6 +9,7 @@ #include <stddef.h> /* for size_t */ #include <stdint.h> /* for (u)int{n}_t */ +#include <stdlib.h> /* for realloc() */ #include <libmisc/macro.h> #include <libmisc/obj.h> @@ -99,6 +100,11 @@ void fmt_print_bool(lo_interface fmt_dest w, bool b); const char * : fmt_print_str , \ bool : fmt_print_bool )(w, val) +/** Same as fmt_print(), but usable from inside of fmt_print(). */ +#define fmt_print2(w, ...) do { LM_FOREACH_PARAM2_(_fmt_param2, (w), __VA_ARGS__) } while (0) +#define _fmt_param2(...) _LM_DEFER2(_fmt_param_indirect)()(__VA_ARGS__) +#define _fmt_param_indirect() _fmt_param + /* print-to-memory ************************************************************/ struct fmt_buf { @@ -116,16 +122,25 @@ LO_IMPLEMENTATION_H(fmt_dest, struct fmt_buf, fmt_buf); _w.len; \ }) -/* justify ********************************************************************/ +#define fmt_asprint(...) ({ \ + struct fmt_buf _w = {}; \ + lo_interface fmt_dest w = lo_box_fmt_buf_as_fmt_dest(&_w); \ + fmt_print(w, __VA_ARGS__); \ + while (_w.cap <= _w.len) { \ + _w.cap = _w.len + 1; \ + _w.len = 0; \ + _w.dat = realloc(_w.dat, _w.cap); \ + fmt_print(w, __VA_ARGS__); \ + } \ + ((char *)_w.dat)[_w.len] = '\0'; \ + _w.dat; \ +}) -/* *grubles about not being allowed to nest things* */ -#define _fmt_param_indirect() _fmt_param -#define _fmt_print2(w, ...) do { LM_FOREACH_PARAM2_(_fmt_param2, (w), __VA_ARGS__) } while (0) -#define _fmt_param2(...) _LM_DEFER2(_fmt_param_indirect)()(__VA_ARGS__) +/* justify ********************************************************************/ #define fmt_print_ljust(w, width, fillchar, ...) do { \ size_t beg = LO_CALL(w, tell); \ - _fmt_print2(w, __VA_ARGS__); \ + fmt_print2(w, __VA_ARGS__); \ while ((LO_CALL(w, tell) - beg) < width) \ fmt_print_byte(w, fillchar); \ } while (0) @@ -133,10 +148,10 @@ LO_IMPLEMENTATION_H(fmt_dest, struct fmt_buf, fmt_buf); #define fmt_print_rjust(w, width, fillchar, ...) do { \ struct fmt_buf _discard = {}; \ lo_interface fmt_dest discard = lo_box_fmt_buf_as_fmt_dest(&_discard); \ - _fmt_print2(discard, __VA_ARGS__); \ + fmt_print2(discard, __VA_ARGS__); \ while (_discard.len++ < width) \ fmt_print_byte(w, fillchar); \ - _fmt_print2(w, __VA_ARGS__); \ + fmt_print2(w, __VA_ARGS__); \ } while (0) void fmt_print_base16_u8_(lo_interface fmt_dest w, uint8_t x); diff --git a/libmisc/tests/test_fmt.c b/libmisc/tests/test_fmt.c index a9157d6..64b3b8a 100644 --- a/libmisc/tests/test_fmt.c +++ b/libmisc/tests/test_fmt.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +#include <stdlib.h> /* for free() */ #include <string.h> /* for strcmp(), memcmp(), memset() */ #include <libmisc/fmt.h> @@ -230,5 +231,13 @@ int main() { test_assert(strcmp(str, "{0x68,0x65,0x6C,0x6C,0x6F,0x00}") == 0); memset(str, 0, sizeof(str)); + char *astr = fmt_asprint(""); + test_assert(astr != NULL && astr[0] == '\0'); + free(astr); + + astr = fmt_asprint("hello ", (base2, 9), (qstr, " world!\n")); + test_assert(strcmp(astr, "hello 1001\" world!\\n\"") == 0); + free(astr); + return 0; } |