Skip to content

Commit 522cc87

Browse files
pks-tgitster
authored andcommitted
utf8: fix truncated string lengths in utf8_strnwidth()
The `utf8_strnwidth()` function accepts an optional string length as input parameter. This parameter can either be set to `-1`, in which case we call `strlen()` on the input. Or it can be set to a positive integer that indicates a precomputed length, which callers typically compute by calling `strlen()` at some point themselves. The input parameter is an `int` though, whereas `strlen()` returns a `size_t`. This can lead to implementation-defined behaviour though when the `size_t` cannot be represented by the `int`. In the general case though this leads to wrap-around and thus to negative string sizes, which is sure enough to not lead to well-defined behaviour. Fix this by accepting a `size_t` instead of an `int` as string length. While this takes away the ability of callers to simply pass in `-1` as string length, it really is trivial enough to convert them to instead pass in `strlen()` instead. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 48050c4 commit 522cc87

File tree

4 files changed

+7
-9
lines changed

4 files changed

+7
-9
lines changed

column.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ struct column_data {
2323
/* return length of 's' in letters, ANSI escapes stripped */
2424
static int item_length(const char *s)
2525
{
26-
return utf8_strnwidth(s, -1, 1);
26+
return utf8_strnwidth(s, strlen(s), 1);
2727
}
2828

2929
/*

pretty.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,7 +1483,7 @@ static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
14831483
int occupied;
14841484
if (!start)
14851485
start = sb->buf;
1486-
occupied = utf8_strnwidth(start, -1, 1);
1486+
occupied = utf8_strnwidth(start, strlen(start), 1);
14871487
occupied += c->pretty_ctx->graph_width;
14881488
padding = (-padding) - occupied;
14891489
}
@@ -1501,7 +1501,7 @@ static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
15011501
placeholder++;
15021502
total_consumed++;
15031503
}
1504-
len = utf8_strnwidth(local_sb.buf, -1, 1);
1504+
len = utf8_strnwidth(local_sb.buf, local_sb.len, 1);
15051505

15061506
if (c->flush_type == flush_left_and_steal) {
15071507
const char *ch = sb->buf + sb->len - 1;

utf8.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,13 +206,11 @@ int utf8_width(const char **start, size_t *remainder_p)
206206
* string, assuming that the string is utf8. Returns strlen() instead
207207
* if the string does not look like a valid utf8 string.
208208
*/
209-
int utf8_strnwidth(const char *string, int len, int skip_ansi)
209+
int utf8_strnwidth(const char *string, size_t len, int skip_ansi)
210210
{
211211
int width = 0;
212212
const char *orig = string;
213213

214-
if (len == -1)
215-
len = strlen(string);
216214
while (string && string < orig + len) {
217215
int skip;
218216
while (skip_ansi &&
@@ -225,7 +223,7 @@ int utf8_strnwidth(const char *string, int len, int skip_ansi)
225223

226224
int utf8_strwidth(const char *string)
227225
{
228-
return utf8_strnwidth(string, -1, 0);
226+
return utf8_strnwidth(string, strlen(string), 0);
229227
}
230228

231229
int is_utf8(const char *text)
@@ -791,7 +789,7 @@ int skip_utf8_bom(char **text, size_t len)
791789
void strbuf_utf8_align(struct strbuf *buf, align_type position, unsigned int width,
792790
const char *s)
793791
{
794-
int slen = strlen(s);
792+
size_t slen = strlen(s);
795793
int display_len = utf8_strnwidth(s, slen, 0);
796794
int utf8_compensation = slen - display_len;
797795

utf8.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ typedef unsigned int ucs_char_t; /* assuming 32bit int */
77

88
size_t display_mode_esc_sequence_len(const char *s);
99
int utf8_width(const char **start, size_t *remainder_p);
10-
int utf8_strnwidth(const char *string, int len, int skip_ansi);
10+
int utf8_strnwidth(const char *string, size_t len, int skip_ansi);
1111
int utf8_strwidth(const char *string);
1212
int is_utf8(const char *text);
1313
int is_encoding_utf8(const char *name);

0 commit comments

Comments
 (0)