From 64bd8ba3749fe473b0708f999e088dfa94d37a2c Mon Sep 17 00:00:00 2001 From: itchyny Date: Sun, 16 Feb 2025 21:40:18 +0900 Subject: [PATCH] fix: `jv_dump_string_trunc` should not break unicode characters (#3249) --- src/jv_print.c | 19 ++++++++++--------- tests/jq.test | 13 +++++++++++++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/jv_print.c b/src/jv_print.c index ffe15234..ae17ec0a 100644 --- a/src/jv_print.c +++ b/src/jv_print.c @@ -381,16 +381,17 @@ jv jv_dump_string(jv x, int flags) { } char *jv_dump_string_trunc(jv x, char *outbuf, size_t bufsize) { - x = jv_dump_string(x,0); - const char* p = jv_string_value(x); - const size_t len = strlen(p); - strncpy(outbuf, p, bufsize); - outbuf[bufsize - 1] = 0; + x = jv_dump_string(x, 0); + const char *str = jv_string_value(x); + const size_t len = strlen(str); + strncpy(outbuf, str, bufsize); if (len > bufsize - 1 && bufsize >= 4) { - // Indicate truncation with '...' - outbuf[bufsize - 2]='.'; - outbuf[bufsize - 3]='.'; - outbuf[bufsize - 4]='.'; + // Indicate truncation with '...' without breaking UTF-8. + const char *s = jvp_utf8_backtrack(outbuf + bufsize - 4, outbuf, NULL); + if (s) bufsize = s + 4 - outbuf; + strcpy(outbuf + bufsize - 4, "..."); + } else { + outbuf[bufsize - 1] = '\0'; } jv_free(x); return outbuf; diff --git a/tests/jq.test b/tests/jq.test index d8758b43..d5eb8dde 100644 --- a/tests/jq.test +++ b/tests/jq.test @@ -1788,6 +1788,19 @@ try -. catch . "very-long-string" "string (\"very-long-...) cannot be negated" +try (.-.) catch . +"very-long-string" +"string (\"very-long-...) and string (\"very-long-...) cannot be subtracted" + +"x" * range(0; 12; 2) + "☆" * 5 | try -. catch . +null +"string (\"☆☆☆...) cannot be negated" +"string (\"xx☆☆...) cannot be negated" +"string (\"xxxx☆☆...) cannot be negated" +"string (\"xxxxxx☆...) cannot be negated" +"string (\"xxxxxxxx...) cannot be negated" +"string (\"xxxxxxxxxx...) cannot be negated" + join(",") ["1",2,true,false,3.4] "1,2,true,false,3.4"