utf8: refactor `strbuf_utf8_replace` to not rely on preallocated buffer
In `strbuf_utf8_replace`, we preallocate the destination buffer and then use `memcpy` to copy bytes into it at computed offsets. This feels rather fragile and is hard to understand at times. Refactor the code to instead use `strbuf_add` and `strbuf_addstr` so that we can be sure that there is no possibility to perform an out-of-bounds write. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Dec 1, 2022 at 15:47 UTC
f930a2394303b902e2973f4308f96529f736b8bc
1 file changed
+13
-21
utf8.c
+13
-21
@@ -365,26 +365,20 @@ void strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
365
void strbuf_utf8_replace(struct strbuf *sb_src, int pos, int width,
366
const char *subst)
367
{
368
- struct strbuf sb_dst = STRBUF_INIT;
369
- char *src = sb_src->buf;
370
- char *end = src + sb_src->len;
371
- char *dst;
372
- int w = 0, subst_len = 0;
368
+ const char *src = sb_src->buf, *end = sb_src->buf + sb_src->len;
369
+ struct strbuf dst;
370
+ int w = 0;
371
374
- if (subst)
375
- subst_len = strlen(subst);
376
- strbuf_grow(&sb_dst, sb_src->len + subst_len);
377
- dst = sb_dst.buf;
372
+ strbuf_init(&dst, sb_src->len);
373
374
while (src < end) {
375
+ const char *old;
376
int glyph_width;
381
- char *old;
377
size_t n;
378
379
while ((n = display_mode_esc_sequence_len(src))) {
385
- memcpy(dst, src, n);
380
+ strbuf_add(&dst, src, n);
381
src += n;
387
- dst += n;
382
}
383
384
if (src >= end)
@@ -404,21 +398,19 @@ void strbuf_utf8_replace(struct strbuf *sb_src, int pos, int width,
398
399
if (glyph_width && w >= pos && w < pos + width) {
400
if (subst) {
407
- memcpy(dst, subst, subst_len);
408
- dst += subst_len;
401
+ strbuf_addstr(&dst, subst);
402
subst = NULL;
403
}
411
- w += glyph_width;
412
- continue;
404
+ } else {
405
+ strbuf_add(&dst, old, src - old);
406
}
414
- memcpy(dst, old, src - old);
415
- dst += src - old;
407
+
408
w += glyph_width;
409
}
418
- strbuf_setlen(&sb_dst, dst - sb_dst.buf);
419
- strbuf_swap(sb_src, &sb_dst);
410
+
411
+ strbuf_swap(sb_src, &dst);
412
out:
421
- strbuf_release(&sb_dst);
413
+ strbuf_release(&dst);
414
}
415
416
/*