diff options
author | Joris Peeraer <jorispeeraer@gmail.com> | 2020-10-22 10:38:03 +0200 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2020-12-07 23:32:06 +1100 |
commit | 5020b14d5419065f1a5ef5aed1be7badee28c9bf (patch) | |
tree | 3a5ecda9ef9027206a3dbb4c3df5fab99803a32d | |
parent | dde0735ac1629aca4f7d41334f25b75dd8d35010 (diff) | |
download | micropython-5020b14d5419065f1a5ef5aed1be7badee28c9bf.tar.gz micropython-5020b14d5419065f1a5ef5aed1be7badee28c9bf.zip |
py/mpprint: Fix length calculation for strings with precision-modifier.
Two issues are tackled:
1. The calculation of the correct length to print is fixed to treat the
precision as a maximum length instead as the exact length.
This is done for both qstr (%q) and for regular str (%s).
2. Fix the incorrect use of mp_printf("%.*s") to mp_print_strn().
Because of the fix of above issue, some testcases that would print
an embedded null-byte (^@ in test-output) would now fail.
The bug here is that "%s" was used to print null-bytes. Instead,
mp_print_strn is used to make sure all bytes are outputted and the
exact length is respected.
Test-cases are added for both %s and %q with a combination of precision
and padding specifiers.
-rw-r--r-- | ports/unix/coverage.c | 2 | ||||
-rw-r--r-- | py/mpprint.c | 13 | ||||
-rw-r--r-- | py/objstr.c | 4 | ||||
-rw-r--r-- | py/objstrunicode.c | 2 | ||||
-rw-r--r-- | tests/unix/extra_coverage.py.exp | 2 |
5 files changed, 12 insertions, 11 deletions
diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 7169c7793b..ef66c4fb59 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -186,7 +186,7 @@ STATIC mp_obj_t extra_coverage(void) { mp_printf(&mp_plat_print, "%ld\n", 123); // long mp_printf(&mp_plat_print, "%lx\n", 0x123); // long hex mp_printf(&mp_plat_print, "%X\n", 0x1abcdef); // capital hex - mp_printf(&mp_plat_print, "%.2s %.3s\n", "abc", "abc"); // fixed string precision + mp_printf(&mp_plat_print, "%.2s %.3s '%4.4s' '%5.5q' '%.3q'\n", "abc", "abc", "abc", MP_QSTR_True, MP_QSTR_True); // fixed string precision mp_printf(&mp_plat_print, "%.*s\n", -1, "abc"); // negative string precision mp_printf(&mp_plat_print, "%b %b\n", 0, 1); // bools #ifndef NDEBUG diff --git a/py/mpprint.c b/py/mpprint.c index 31cf73bb58..3218bd2f4d 100644 --- a/py/mpprint.c +++ b/py/mpprint.c @@ -484,10 +484,10 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { qstr qst = va_arg(args, qstr); size_t len; const char *str = (const char *)qstr_data(qst, &len); - if (prec < 0) { - prec = len; + if (prec >= 0 && (size_t)prec < len) { + len = prec; } - chrs += mp_print_strn(print, str, prec, flags, fill, width); + chrs += mp_print_strn(print, str, len, flags, fill, width); break; } case 's': { @@ -499,10 +499,11 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { break; } #endif - if (prec < 0) { - prec = strlen(str); + size_t len = strlen(str); + if (prec >= 0 && (size_t)prec < len) { + len = prec; } - chrs += mp_print_strn(print, str, prec, flags, fill, width); + chrs += mp_print_strn(print, str, len, flags, fill, width); break; } case 'd': { diff --git a/py/objstr.c b/py/objstr.c index 84728e6f2d..9f8da873d6 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -123,10 +123,10 @@ STATIC void str_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t bool is_bytes = true; #endif if (kind == PRINT_RAW || (!MICROPY_PY_BUILTINS_STR_UNICODE && kind == PRINT_STR && !is_bytes)) { - mp_printf(print, "%.*s", str_len, str_data); + print->print_strn(print->data, (const char *)str_data, str_len); } else { if (is_bytes) { - mp_print_str(print, "b"); + print->print_strn(print->data, "b", 1); } mp_str_print_quoted(print, str_data, str_len, is_bytes); } diff --git a/py/objstrunicode.c b/py/objstrunicode.c index b21df22a3b..ed79ad68a9 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -92,7 +92,7 @@ STATIC void uni_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t } #endif if (kind == PRINT_STR) { - mp_printf(print, "%.*s", str_len, str_data); + print->print_strn(print->data, (const char *)str_data, str_len); } else { uni_print_quoted(print, str_data, str_len); } diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 257224108a..d97de2c0ef 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -4,7 +4,7 @@ 123 123 1ABCDEF -ab abc +ab abc ' abc' ' True' 'Tru' false true (null) |