Hello,

I've discovered that the pg_bsd_indent test added here makes an
ASAN-instrumented build fail on:
ASAN_OPTIONS=detect_leaks=0:strict_string_checks=1 make check-world
as follows:
# +++ tap check in src/tools/pg_bsd_indent +++
t/001_pg_bsd_indent.pl .. 1/?
#   Failed test 'pg_bsd_indent succeeds on binary'
#   at t/001_pg_bsd_indent.pl line 41.

#   Failed test 'pg_bsd_indent output matches for binary'
#   at t/001_pg_bsd_indent.pl line 50.

#   Failed test 'pg_bsd_indent succeeds on comments'
#   at t/001_pg_bsd_indent.pl line 41.

#   Failed test 'pg_bsd_indent output matches for comments'
#   at t/001_pg_bsd_indent.pl line 50.
t/001_pg_bsd_indent.pl .. 10/?
...
regress_log_001_pg_bsd_indent contains:
# Running: pg_bsd_indent .../src/tools/pg_bsd_indent/tests/binary.0 binary.out -P.../src/tools/pg_bsd_indent/tests/binary.pro
=================================================================
==2124067==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60600000005a at pc 0x560aa8972dae bp 0x7ffebd080460 sp 0x7ffebd07fc08
READ of size 40 at 0x60600000005a thread T0
    #0 0x560aa8972dad in __interceptor_strspn.part.0 
(.../src/tools/pg_bsd_indent/pg_bsd_indent+0x5edad)
    #1 0x560aa8a3f495 in lexi .../src/tools/pg_bsd_indent/lexi.c:258
    #2 0x560aa8a3451d in main .../src/tools/pg_bsd_indent/indent.c:269
    #3 0x7f6ffab1ad8f in __libc_start_call_main 
../sysdeps/nptl/libc_start_call_main.h:58
    #4 0x7f6ffab1ae3f in __libc_start_main_impl ../csu/libc-start.c:392
    #5 0x560aa894b7d4 in _start 
(.../src/tools/pg_bsd_indent/pg_bsd_indent+0x377d4)

0x60600000005a is located 0 bytes to the right of 58-byte region 
[0x606000000020,0x60600000005a)
allocated by thread T0 here:
    #0 0x560aa89e4980 in __interceptor_realloc.part.0 
(.../src/tools/pg_bsd_indent/pg_bsd_indent+0xd0980)
    #1 0x560aa8a3d24e in fill_buffer .../src/tools/pg_bsd_indent/io.c:365

SUMMARY: AddressSanitizer: heap-buffer-overflow (.../src/tools/pg_bsd_indent/pg_bsd_indent+0x5edad) in __interceptor_strspn.part.0
...

I understand that that code is almost as ancient as me and it works as
intended (fill_buffer() doesn't null-terminate a buffer), but may be this is
worth fixing in the Postgres source tree to keep the whole testing baseline
high (if someone finds strict_string_checks useful). If so, perhaps
something like the attached will do.

Best regards,
Alexander
diff --git a/src/tools/pg_bsd_indent/lexi.c b/src/tools/pg_bsd_indent/lexi.c
index 943bf7ce6b..1af8167493 100644
--- a/src/tools/pg_bsd_indent/lexi.c
+++ b/src/tools/pg_bsd_indent/lexi.c
@@ -212,6 +212,26 @@ is_func_definition(char *tp)
     return false;
 }
 
+static size_t
+strspn_n(const char *s1, const char *s2)
+{
+	const char *p = s1, *spanp;
+	char c, sc;
+	/*
+	 * Skip any characters in s2, excluding the terminating \0 and \n.
+	 */
+cont:
+	c = *p++;
+	for (spanp = s2; (sc = *spanp++) != 0;)
+		if (sc == c)
+			goto cont;
+		else if (sc == '\n')
+			break;
+	return (p - 1 - s1);
+}
+
+#define strspn(s1, s2) strspn_n(s1, s2)
+
 int
 lexi(struct parser_state *state)
 {

Reply via email to