Attempted rewrite of _display_get_fmt()`, it currently doesn"t work. To compile using the old functional but (probably) unsafe function, pass `-D_DEBUG_USE_UNSAFE_DISPLAY_FMT_ARGS` in `CFLAGS`.

TODO: Find out why _display_get_fmt_n()` is so broken...

TODO: Make `_display_get_fmt()` a function alias instead of macro definition

Fixed `deprecated` macro conflicts with attribute usage. (renamed to `_deprecated`)

Fortune for naka's current commit: Half blessing − 半吉
display_format_safety
Avril 3 years ago
parent dca7e48d4a
commit 0db8d882d0
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -18,11 +18,13 @@
#define _cold __attribute__((cold)) #define _cold __attribute__((cold))
#define _hot __attribute__((hot)) #define _hot __attribute__((hot))
#define _dead __attribute__((unused))
#ifndef __cplusplus #ifndef __cplusplus
#define noreturn __attribute__((noreturn)) #define noreturn __attribute__((noreturn))
#define deprecated __attribute__((deprecated)) #define _deprecated __attribute__((deprecated))
#define deprecated_message(str) __attribute__((deprecated(str))) #define deprecated_message(str) __attribute__((deprecated(str)))
#define _deprecated_msg(str) deprecated_message(str)
#endif #endif
#define noinline __attribute__((noinline)) #define noinline __attribute__((noinline))

@ -53,8 +53,59 @@ static inline usize strncat_n(char*pOUT dest, const char* restrict src, usize n)
return strncpy_n(dest+dl, src, n); return strncpy_n(dest+dl, src, n);
} }
//TODO: This works, but seems inherantly unsafe. Rewrite to use the above `strn*_n()` functions for better length tracking. //TODO: This isn't working at all...
static usize _display_get_fmt(dispflags_t flags, bool matched, usize _len, char str[pOUT _len]) #ifdef _DEBUG_USE_UNSAFE_DISPLAY_FMT_ARGS
_dead
#endif
static usize _display_get_fmt_n(dispflags_t flags, bool matched, usize _n, char str[pOUT _n])
{
register usize n = _n, fw=0;
const char* fmts[] = {
DFLAGSET(flags, FAILURES)
? "failure: "
: "",
"match: ",
"%lu: ",
SLICE_FORMAT,
" (len %lu)",
(const char*)NULL,
};
usize w = s_strncpy_n(str, n, fmts[!!matched], n); // SAFETY: Will never read past `fmts[x]` nul-terminator, so setting n as both dest and src length here is safe.
//TODO: Fix this... It isn't working...
#define ADDSTR(s) do { \
debug_assert((s)); \
w = MINx(s_strncat_n(str, n, (s), n), n); \
/* Remove written from `n` */ \
n -= w; \
/* Check if we have written into the limit (if so, w will be equal to n above, since w is high-bounded to n by `MINx()` above. So if n is 0, we have hit the limit. */ \
ifU(!n) { \
/*XXX: Should this be `str[w-1]?` If this assert fails then yes it should. */ \
debug_assert(w < _n); \
str[w] = 0; \
return fw + w; \
} \
/* Increase `str` pointer by written */ \
str += w; \
/* Increase return value by written. */ \
fw += w; \
} while(0)
if(DFLAGSET(flags, NUMBER)) ADDSTR(fmts[2]);
if(DFLAGSET(flags, SLICE)) ADDSTR(fmts[3]);
if(DFLAGSET(flags, LENGTH)) ADDSTR(fmts[4]);
ADDSTR("\n");
TRACE("Output string written: %lu, (rlen %lu)", fw, n);
#undef ADDSTR
return fw;
}
//XXX: This works, but seems inherantly unsafe. Rewrite to use the above `strn*_n()` functions for better length tracking.
#ifndef _DEBUG_USE_UNSAFE_DISPLAY_FMT_ARGS
_dead deprecated_message("this is unsafe, use `_display_get_fmt_n`")
#endif
static usize _display_get_fmt0(dispflags_t flags, bool matched, usize _len, char str[pOUT _len])
{ {
register usize len = _len; register usize len = _len;
static const char* fmts[] = { "match: ", "%lu: ", SLICE_FORMAT, " (len %lu)", "failure: ", (const char*)NULL }; static const char* fmts[] = { "match: ", "%lu: ", SLICE_FORMAT, " (len %lu)", "failure: ", (const char*)NULL };
@ -72,6 +123,12 @@ static usize _display_get_fmt(dispflags_t flags, bool matched, usize _len, char
#undef ADDSTR #undef ADDSTR
} }
#ifdef _DEBUG_USE_UNSAFE_DISPLAY_FMT_ARGS
#define _display_get_fmt(...) _display_get_fmt0(__VA_ARGS__)
#else
#define _display_get_fmt(...) _display_get_fmt_n(__VA_ARGS__)
#endif
static void _display_normal(FILE* output, dispin_t*pIN input, dispflags_t flags) static void _display_normal(FILE* output, dispin_t*pIN input, dispflags_t flags)
{ {
bool matched = input->matched; bool matched = input->matched;
@ -91,9 +148,14 @@ static void _display_normal(FILE* output, dispin_t*pIN input, dispflags_t flags)
#endif #endif
INFO("Mapped region slice for %lu, pre-transform (at %p): " SLICE_FORMAT ", len: %lu", i+1, base, SLICE_FORMAT_ARGS(&cslice), cslice.len); INFO("Mapped region slice for %lu, pre-transform (at %p): " SLICE_FORMAT ", len: %lu", i+1, base, SLICE_FORMAT_ARGS(&cslice), cslice.len);
//Honour `flags` // --- get format string from `flags` ---
char fmt[200]; //TODO: Find the realistic max for this. char fmt[200]; //TODO: Find the realistic max for this.
fmt[_display_get_fmt(flags, matched, 100, fmt)] = 0; usize fmtw = _display_get_fmt(flags, matched, sizeof(fmt)-1, fmt);
assert(fmtw+1 < sizeof(fmt));
fmt[fmtw+1] = 0;
// ---
TRACE("Format string get: `%s' (%lu)", fmt, fmtw);
fprintf(output, fmt, i+1, pos.start, pos.end, pos.end-pos.start); fprintf(output, fmt, i+1, pos.start, pos.end, pos.end-pos.start);
} }

Loading…
Cancel
Save