From bc16854ccb359a0d2323a2befd4739fc720f737e Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Fri, 6 May 2022 21:09:13 +0100 Subject: [PATCH] Get rid of MG_ENABLE_LOG, change mg_hexdump() --- Makefile | 2 +- docs/README.md | 71 +++++++++++++++++-------------------------- mongoose.c | 79 +++++++++++++++++++++++++----------------------- mongoose.h | 21 +------------ src/config.h | 4 --- src/dns.c | 5 ++- src/log.c | 38 +++++++++++++++++++++-- src/log.h | 16 +--------- src/sock.c | 9 +++--- src/str.c | 27 ----------------- src/str.h | 1 - test/fuzz.c | 5 ++- test/unit_test.c | 6 ++-- 13 files changed, 117 insertions(+), 167 deletions(-) diff --git a/Makefile b/Makefile index d7a29dc6..5d0d1e0c 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,7 @@ unpacked: $(CC) -I. mongoose.c test/unit_test.c -o $@ fuzzer: mongoose.c mongoose.h Makefile test/fuzz.c - clang++ mongoose.c test/fuzz.c $(WARN) $(INCS) $(TFLAGS) $(EXTRA) -DMG_ENABLE_LINES -DMG_ENABLE_LOG=0 -fsanitize=fuzzer,signed-integer-overflow,address -Wno-deprecated -o $@ + clang++ mongoose.c test/fuzz.c $(WARN) $(INCS) $(TFLAGS) $(EXTRA) -DMG_ENABLE_LINES -fsanitize=fuzzer,signed-integer-overflow,address -Wno-deprecated -o $@ fuzz: fuzzer $(RUN) ./fuzzer diff --git a/docs/README.md b/docs/README.md index 5bbec5ff..13dc89d1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -264,7 +264,7 @@ option during build time, use the `-D OPTION` compiler flag: $ cc app0.c mongoose.c # Use defaults! $ cc app1.c mongoose.c -D MG_ENABLE_IPV6=1 # Build with IPv6 enabled $ cc app2.c mongoose.c -D MG_ARCH=MG_ARCH_FREERTOS_LWIP # Set architecture -$ cc app3.c mongoose.c -D MG_ENABLE_SSI=0 -D MG_ENABLE_LOG=0 # Multiple options +$ cc app3.c mongoose.c -D MG_ENABLE_SSI=0 -D MG_IO_SIZE=8192 # Multiple options ``` The list of supported architectures is defined in the [arch.h](https://github.com/cesanta/mongoose/blob/master/src/arch.h) @@ -294,7 +294,6 @@ Here is a list of build constants and their default values: |MG_ENABLE_MBEDTLS | 0 | Enable mbedTLS library | |MG_ENABLE_OPENSSL | 0 | Enable OpenSSL library | |MG_ENABLE_IPV6 | 0 | Enable IPv6 | -|MG_ENABLE_LOG | 1 | Enable `LOG()` macro | |MG_ENABLE_MD5 | 0 | Use native MD5 implementation | |MG_ENABLE_SSI | 1 | Enable serving SSI files by `mg_http_serve_dir()` | |MG_ENABLE_CUSTOM_RANDOM | 0 | Provide custom RNG function `mg_random()` | @@ -2371,30 +2370,6 @@ while (mg_commalist(&s, &k, &v)) // This loop output: (int) k.len, k.ptr, (int) v.len, v.ptr); // [b] set to [777] ``` -### mg\_hexdump() - -```c -char *mg_hexdump(const void *buf, int len); -``` - -Hexdump binary data `buf`, `len` into malloc-ed buffer and return it. -It is a caller's responsibility to free() returned pointer. - -Parameters: -- `buf` - Data to hexdump -- `len` - Data length - -Return value: malloc-ed buffer with hexdumped data - -Usage example: - -```c -char arr[] = "\0x1\0x2\0x3"; -char *hex = mg_hexdump(arr, sizeof(arr)); -LOG(LL_INFO, ("%s", hex)); // Output "0000 01 02 03 00"; -free(hex); -``` - ### mg\_hex() ```c @@ -3438,27 +3413,17 @@ use these functions for its own purposes as well as the rest of Mongoose API. ```c #define LOG(level, args) +#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args) +#define MG_INFO(args) MG_LOG(MG_LL_INFO, args) +#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args) +#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args) ``` -General way to log is using `LOG` macro. -`LOG` prints to log only is `MG_ENABLE_LOG` macro defined, otherwise is does nothing. - -This macro has two arguments: log level and information to log. The second argument is a printf-alike format string. - -Log levels defined as: -```c -enum { LL_NONE, LL_ERROR, LL_INFO, LL_DEBUG, LL_VERBOSE_DEBUG }; -``` - -Parameters: -- `level` - Log level, see levels above -- `args` - Information to log - -Return value: None - +Logging macros. Usage example: + ```c -LOG(LL_ERROR, ("Hello %s!", "world")); // Output "Hello, world" +MG_INFO(("Hello %s!", "world")); // Output "Hello, world" ``` ### mg\_log\_set() @@ -3519,6 +3484,26 @@ void log_via_printf(const void *buf, size_t len, void *userdata) { mg_log_set_callback(&log_via_printf, NULL); ``` +### mg\_hexdump() + +```c +void mg_hexdump(const void *buf, int len); +``` + +Log a hex dump of binary data `buf`, `len`. + +Parameters: +- `buf` - Data pointer +- `len` - Data length + +Return value: none + +Usage example: + +```c +mg_hexdump(c->recv.buf, c->recv.len); // Hex dump incoming data +``` + ## Filesystem ### FS virtualisation diff --git a/mongoose.c b/mongoose.c index f5eee27e..793c3d8a 100644 --- a/mongoose.c +++ b/mongoose.c @@ -260,9 +260,8 @@ static void dns_cb(struct mg_connection *c, int ev, void *ev_data, struct mg_dns_message dm; int resolved = 0; if (mg_dns_parse(c->recv.buf, c->recv.len, &dm) == false) { - char *s = mg_hexdump(c->recv.buf, c->recv.len); - MG_ERROR(("Unexpected DNS response:\n%s\n", s)); - free(s); + MG_ERROR(("Unexpected DNS response:")); + mg_hexdump(c->recv.buf, c->recv.len); } else { MG_VERBOSE(("%s %d", dm.name, dm.resolved)); for (d = (struct dns_data *) c->mgr->active_dns_requests; d != NULL; @@ -1996,11 +1995,19 @@ void mg_iobuf_free(struct mg_iobuf *io) { -#if MG_ENABLE_LOG +static void logc(int c) { + putchar(c); +} + +static void logs(const char *buf, size_t len) { + size_t i; + for (i = 0; i < len; i++) logc(buf[i]); +} + static void mg_log_stdout(const void *buf, size_t len, void *userdata) { (void) userdata, (void) buf, (void) len; #if MG_ENABLE_FILE - fwrite(buf, 1, len, stdout); + logs((const char *) buf, len); #endif } @@ -2059,7 +2066,31 @@ void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *fnd) { s_fn = fn; s_fn_param = fnd; } -#endif + +static unsigned char nibble(unsigned c) { + return (unsigned char) (c < 10 ? c + '0' : c + 'W'); +} + +#define ISPRINT(x) ((x) >= ' ' && (x) <= '~') +void mg_hexdump(const void *buf, size_t len) { + const unsigned char *p = (const unsigned char *) buf; + unsigned char ascii[16], alen = 0; + size_t i; + for (i = 0; i < len; i++) { + if ((i % 16) == 0) { + // Print buffered ascii chars + if (i > 0) logs(" ", 2), logs((char *) ascii, 16), logc('\n'), alen = 0; + // Print hex address, then \t + logc(nibble((i >> 12) & 15)), logc(nibble((i >> 8) & 15)), + logc(nibble((i >> 4) & 15)), logc('0'), logs(" ", 3); + } + logc(nibble(p[i] >> 4)), logc(nibble(p[i] & 15)); // Two nibbles, e.g. c5 + logc(' '); // Space after hex number + ascii[alen++] = ISPRINT(p[i]) ? p[i] : '.'; // Add to the ascii buf + } + while (alen < 16) logs(" ", 3), ascii[alen++] = ' '; + logs(" ", 2), logs((char *) ascii, 16), logc('\n'); +} #ifdef MG_ENABLE_LINES #line 1 "src/md5.c" @@ -3222,17 +3253,16 @@ static void iolog(struct mg_connection *c, char *buf, long n, bool r) { union usa usa; char t1[50] = "", t2[50] = ""; socklen_t slen = sizeof(usa.sin); - char *s = mg_hexdump(buf, (size_t) n); struct mg_addr a; memset(&usa, 0, sizeof(usa)); memset(&a, 0, sizeof(a)); if (getsockname(FD(c), &usa.sa, &slen) < 0) (void) 0; // Ignore result tomgaddr(&usa, &a, c->rem.is_ip6); - MG_INFO(("\n-- %lu %s %s %s %s %ld\n%s", c->id, + MG_INFO(("\n-- %lu %s %s %s %s %ld", c->id, mg_straddr(&a, t1, sizeof(t1)), r ? "<-" : "->", - mg_straddr(&c->rem, t2, sizeof(t2)), c->label, n, s)); - free(s); - (void) t1, (void) t2; // Silence warnings for MG_ENABLE_LOG=0 + mg_straddr(&c->rem, t2, sizeof(t2)), c->label, n)); + + mg_hexdump(buf, (size_t) n); } if (r) { struct mg_str evd = mg_str_n(buf, (size_t) n); @@ -3935,33 +3965,6 @@ size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...) { return n; } -char *mg_hexdump(const void *buf, size_t len) { - const unsigned char *p = (const unsigned char *) buf; - size_t i, idx, n = 0, ofs = 0, dlen = len * 5 + 100; - char ascii[17] = "", *dst = (char *) calloc(1, dlen); - if (dst == NULL) return dst; - for (i = 0; i < len; i++) { - idx = i % 16; - if (idx == 0) { - if (i > 0 && dlen > n) - n += mg_snprintf(dst + n, dlen - n, " %s\n", ascii); - if (dlen > n) - n += mg_snprintf(dst + n, dlen - n, "%04x ", (int) (i + ofs)); - } - if (dlen < n) break; - n += mg_snprintf(dst + n, dlen - n, " %02x", p[i]); - ascii[idx] = (char) (p[i] < 0x20 || p[i] > 0x7e ? '.' : p[i]); - ascii[idx + 1] = '\0'; - } - while (i++ % 16) { - if (n < dlen) n += mg_snprintf(dst + n, dlen - n, "%s", " "); - } - if (n < dlen) n += mg_snprintf(dst + n, dlen - n, " %s\n", ascii); - if (n > dlen - 1) n = dlen - 1; - dst[n] = '\0'; - return dst; -} - char *mg_hex(const void *buf, size_t len, char *to) { const unsigned char *p = (const unsigned char *) buf; const char *hex = "0123456789abcdef"; diff --git a/mongoose.h b/mongoose.h index 2c1c882c..a5585046 100644 --- a/mongoose.h +++ b/mongoose.h @@ -544,10 +544,6 @@ int sscanf(const char *, const char *, ...); #define MG_ENABLE_IPV6 0 #endif -#ifndef MG_ENABLE_LOG -#define MG_ENABLE_LOG 1 -#endif - #ifndef MG_ENABLE_MD5 #define MG_ENABLE_MD5 0 #endif @@ -649,7 +645,6 @@ bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v); bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v); size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap); size_t mg_snprintf(char *, size_t, const char *fmt, ...) PRINTF_LIKE(3, 4); -char *mg_hexdump(const void *buf, size_t len); char *mg_hex(const void *buf, size_t len, char *dst); void mg_unhex(const char *buf, size_t len, unsigned char *to); unsigned long mg_unhexn(const char *s, size_t len); @@ -669,27 +664,13 @@ void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2); bool mg_log_prefix(int ll, const char *file, int line, const char *fname); void mg_log_set(const char *spec); void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *param); - -// Let the compiler always see the log invocation in order to check parameters -// For MG_ENABLE_LOG=0 case, the call will be optimised out, anyway - -#if MG_ENABLE_LOG +void mg_hexdump(const void *buf, size_t len); #define MG_LOG(level, args) \ do { \ if (mg_log_prefix((level), __FILE__, __LINE__, __func__)) mg_log args; \ } while (0) -#else - -#define MG_LOG(level, args) \ - do { \ - (void) level; \ - if (0) mg_log args; \ - } while (0) - -#endif - #define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args) #define MG_INFO(args) MG_LOG(MG_LL_INFO, args) #define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args) diff --git a/src/config.h b/src/config.h index 21dea125..d239befa 100644 --- a/src/config.h +++ b/src/config.h @@ -28,10 +28,6 @@ #define MG_ENABLE_IPV6 0 #endif -#ifndef MG_ENABLE_LOG -#define MG_ENABLE_LOG 1 -#endif - #ifndef MG_ENABLE_MD5 #define MG_ENABLE_MD5 0 #endif diff --git a/src/dns.c b/src/dns.c index a3ea8c67..5cf41472 100644 --- a/src/dns.c +++ b/src/dns.c @@ -148,9 +148,8 @@ static void dns_cb(struct mg_connection *c, int ev, void *ev_data, struct mg_dns_message dm; int resolved = 0; if (mg_dns_parse(c->recv.buf, c->recv.len, &dm) == false) { - char *s = mg_hexdump(c->recv.buf, c->recv.len); - MG_ERROR(("Unexpected DNS response:\n%s\n", s)); - free(s); + MG_ERROR(("Unexpected DNS response:")); + mg_hexdump(c->recv.buf, c->recv.len); } else { MG_VERBOSE(("%s %d", dm.name, dm.resolved)); for (d = (struct dns_data *) c->mgr->active_dns_requests; d != NULL; diff --git a/src/log.c b/src/log.c index 2d9e328e..6d3cb8bf 100644 --- a/src/log.c +++ b/src/log.c @@ -1,11 +1,19 @@ #include "log.h" #include "util.h" -#if MG_ENABLE_LOG +static void logc(int c) { + putchar(c); +} + +static void logs(const char *buf, size_t len) { + size_t i; + for (i = 0; i < len; i++) logc(buf[i]); +} + static void mg_log_stdout(const void *buf, size_t len, void *userdata) { (void) userdata, (void) buf, (void) len; #if MG_ENABLE_FILE - fwrite(buf, 1, len, stdout); + logs((const char *) buf, len); #endif } @@ -64,4 +72,28 @@ void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *fnd) { s_fn = fn; s_fn_param = fnd; } -#endif + +static unsigned char nibble(unsigned c) { + return (unsigned char) (c < 10 ? c + '0' : c + 'W'); +} + +#define ISPRINT(x) ((x) >= ' ' && (x) <= '~') +void mg_hexdump(const void *buf, size_t len) { + const unsigned char *p = (const unsigned char *) buf; + unsigned char ascii[16], alen = 0; + size_t i; + for (i = 0; i < len; i++) { + if ((i % 16) == 0) { + // Print buffered ascii chars + if (i > 0) logs(" ", 2), logs((char *) ascii, 16), logc('\n'), alen = 0; + // Print hex address, then \t + logc(nibble((i >> 12) & 15)), logc(nibble((i >> 8) & 15)), + logc(nibble((i >> 4) & 15)), logc('0'), logs(" ", 3); + } + logc(nibble(p[i] >> 4)), logc(nibble(p[i] & 15)); // Two nibbles, e.g. c5 + logc(' '); // Space after hex number + ascii[alen++] = ISPRINT(p[i]) ? p[i] : '.'; // Add to the ascii buf + } + while (alen < 16) logs(" ", 3), ascii[alen++] = ' '; + logs(" ", 2), logs((char *) ascii, 16), logc('\n'); +} diff --git a/src/log.h b/src/log.h index 5d07c00a..0b02ca9a 100644 --- a/src/log.h +++ b/src/log.h @@ -8,27 +8,13 @@ void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2); bool mg_log_prefix(int ll, const char *file, int line, const char *fname); void mg_log_set(const char *spec); void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *param); - -// Let the compiler always see the log invocation in order to check parameters -// For MG_ENABLE_LOG=0 case, the call will be optimised out, anyway - -#if MG_ENABLE_LOG +void mg_hexdump(const void *buf, size_t len); #define MG_LOG(level, args) \ do { \ if (mg_log_prefix((level), __FILE__, __LINE__, __func__)) mg_log args; \ } while (0) -#else - -#define MG_LOG(level, args) \ - do { \ - (void) level; \ - if (0) mg_log args; \ - } while (0) - -#endif - #define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args) #define MG_INFO(args) MG_LOG(MG_LL_INFO, args) #define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args) diff --git a/src/sock.c b/src/sock.c index e00e27e4..987b05bc 100644 --- a/src/sock.c +++ b/src/sock.c @@ -117,17 +117,16 @@ static void iolog(struct mg_connection *c, char *buf, long n, bool r) { union usa usa; char t1[50] = "", t2[50] = ""; socklen_t slen = sizeof(usa.sin); - char *s = mg_hexdump(buf, (size_t) n); struct mg_addr a; memset(&usa, 0, sizeof(usa)); memset(&a, 0, sizeof(a)); if (getsockname(FD(c), &usa.sa, &slen) < 0) (void) 0; // Ignore result tomgaddr(&usa, &a, c->rem.is_ip6); - MG_INFO(("\n-- %lu %s %s %s %s %ld\n%s", c->id, + MG_INFO(("\n-- %lu %s %s %s %s %ld", c->id, mg_straddr(&a, t1, sizeof(t1)), r ? "<-" : "->", - mg_straddr(&c->rem, t2, sizeof(t2)), c->label, n, s)); - free(s); - (void) t1, (void) t2; // Silence warnings for MG_ENABLE_LOG=0 + mg_straddr(&c->rem, t2, sizeof(t2)), c->label, n)); + + mg_hexdump(buf, (size_t) n); } if (r) { struct mg_str evd = mg_str_n(buf, (size_t) n); diff --git a/src/str.c b/src/str.c index 3a35bea3..cb5693bf 100644 --- a/src/str.c +++ b/src/str.c @@ -165,33 +165,6 @@ size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...) { return n; } -char *mg_hexdump(const void *buf, size_t len) { - const unsigned char *p = (const unsigned char *) buf; - size_t i, idx, n = 0, ofs = 0, dlen = len * 5 + 100; - char ascii[17] = "", *dst = (char *) calloc(1, dlen); - if (dst == NULL) return dst; - for (i = 0; i < len; i++) { - idx = i % 16; - if (idx == 0) { - if (i > 0 && dlen > n) - n += mg_snprintf(dst + n, dlen - n, " %s\n", ascii); - if (dlen > n) - n += mg_snprintf(dst + n, dlen - n, "%04x ", (int) (i + ofs)); - } - if (dlen < n) break; - n += mg_snprintf(dst + n, dlen - n, " %02x", p[i]); - ascii[idx] = (char) (p[i] < 0x20 || p[i] > 0x7e ? '.' : p[i]); - ascii[idx + 1] = '\0'; - } - while (i++ % 16) { - if (n < dlen) n += mg_snprintf(dst + n, dlen - n, "%s", " "); - } - if (n < dlen) n += mg_snprintf(dst + n, dlen - n, " %s\n", ascii); - if (n > dlen - 1) n = dlen - 1; - dst[n] = '\0'; - return dst; -} - char *mg_hex(const void *buf, size_t len, char *to) { const unsigned char *p = (const unsigned char *) buf; const char *hex = "0123456789abcdef"; diff --git a/src/str.h b/src/str.h index d702ae42..e688c321 100644 --- a/src/str.h +++ b/src/str.h @@ -33,7 +33,6 @@ bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v); bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v); size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap); size_t mg_snprintf(char *, size_t, const char *fmt, ...) PRINTF_LIKE(3, 4); -char *mg_hexdump(const void *buf, size_t len); char *mg_hex(const void *buf, size_t len, char *dst); void mg_unhex(const char *buf, size_t len, unsigned char *to); unsigned long mg_unhexn(const char *s, size_t len); diff --git a/test/fuzz.c b/test/fuzz.c index 3a30178e..123e3816 100644 --- a/test/fuzz.c +++ b/test/fuzz.c @@ -7,6 +7,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *, size_t); #endif int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + mg_log_set("0"); + struct mg_dns_message dm; mg_dns_parse(data, size, &dm); mg_dns_parse(NULL, 0, &dm); @@ -36,9 +38,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mg_base64_encode(data, (int) size, buf); mg_base64_encode(NULL, 0, buf); - char *hexdump = mg_hexdump(data, size); - free(hexdump); - mg_globmatch((char *) data, size, (char *) data, size); struct mg_str k, v, s = mg_str_n((char *) data, size); diff --git a/test/unit_test.c b/test/unit_test.c index 83874918..5ab03407 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -1426,13 +1426,11 @@ static void test_dns(void) { } static void test_util(void) { - char buf[100], *s = mg_hexdump("abc", 3), *p; + char buf[100], *p, *s; struct mg_addr a; - ASSERT(s != NULL); - free(s); memset(&a, 0, sizeof(a)); ASSERT(mg_file_printf(&mg_fs_posix, "data.txt", "%s", "hi") == true); - if (system("ls -l") != 0) (void) 0; + // if (system("ls -l") != 0) (void) 0; ASSERT((p = mg_file_read(&mg_fs_posix, "data.txt", NULL)) != NULL); ASSERT(strcmp(p, "hi") == 0); free(p);