This is an archive of the discontinued LLVM Phabricator instance.

[MSAN] add __b64_pton and __b64_ntop intercepts
ClosedPublic

Authored by kda on Mar 31 2022, 1:35 PM.

Diff Detail

Event Timeline

kda created this revision.Mar 31 2022, 1:35 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 31 2022, 1:35 PM
kda requested review of this revision.Mar 31 2022, 1:35 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 31 2022, 1:35 PM
Herald added a subscriber: Restricted Project. · View Herald Transcript
kda updated this revision to Diff 419562.Mar 31 2022, 1:37 PM

improved comparison

kda updated this revision to Diff 419571.Mar 31 2022, 2:42 PM

remove unused include

vitalybuka added inline comments.Apr 1 2022, 5:45 PM
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
2508

is "res >= targsize" possible?
Isn't this return -1 on overflow?

2514

COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);

COMMON_INTERCEPTOR_READ_STRING usually use for parsers which may read just a part of the string
As I understand on success __b64_pton will read entire string

2518

is "res > targsize" possible?
also this one does not set trailing \0, so no +1

compiler-rt/test/msan/Linux/b64.cpp
4

that change is sanitizer_common
so we want a the which is executed with check-sanitizer:
e.g. compiler-rt/test/sanitizer_common/TestCases/Linux/b64.cpp

4

in addition to msan/Linux/b64.cpp

kda added inline comments.Apr 4 2022, 11:34 AM
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
2508

Since the code is adding one ('+ 1'), I wanted to avoid writing past the end. So, the check is intended to prevent 'res == targsize'.

2514

READ_STRING depends on null termination, which I believe this method does as well. There is no length provided, how else would the length be determined.

https://elixir.bootlin.com/glibc/glibc-2.17/source/resolv/base64.c#L209

2518

Unit test fails without the '+ 1'.

Similar to above, check is to prevent writing beyond end of target.

compiler-rt/test/msan/Linux/b64.cpp
4

I'm not sure what to do.

Leave this one here, and clone it with different RUN lines to 'sanitizer_common/TestCases/Linux'?

vitalybuka added inline comments.Apr 4 2022, 12:18 PM
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
2508
https://elixir.bootlin.com/glibc/glibc-2.17/source/resolv/base64.c#L184
if (datalength >= targsize)
		return (-1);
target[datalength] = '\0'

I do not insist, just recommend, COMMON_INTERCEPTOR_WRITE_RANGE(ctx, target, res + 1) is enough
if we have issues with so other implementation we can add workaround later

2514

#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n) \

COMMON_INTERCEPTOR_READ_RANGE((ctx), (s),                       \
  common_flags()->strict_string_checks ? (internal_strlen(s)) + 1 : (n) )

strict_string_checks (default: false) means even if REAL() reads only few first byte of the string, entire string must be correct up to the null terminator. Otherwise it's UB for some str functions. However this check is hard to enable in real code, a lot code call str functions on non null terminated strings.

So the patch as-is is essentially: COMMON_INTERCEPTOR_READ_RANGE(ctx, src, 0); which is NOOP

COMMON_INTERCEPTOR_READ_STRING(ctx, src, internal_strlen(src) + 1); can work here, but it's equivalent to
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);

2518

is "res > targsize" possible?
also this one does not set trailing \0, so no +1

Same as above (res < targsize) seem unnecessary
if (res + 1) is overflow REAL() must return -1

2518

Unit test fails without the '+ 1'.

Similar to above, check is to prevent writing beyond end of target.

https://elixir.bootlin.com/glibc/glibc-2.17/source/resolv/base64.c#L248
You are correct, according to the code, the last written char is target[res], so should be res + 1,

compiler-rt/test/msan/Linux/b64.cpp
4

yes, and drop CHECK: WARNING stuff as we can't run different sanitizers there
also you can add some corner-case we discussing above

13

there is a leak of dst

char dst[dst_len]; ?

kda updated this revision to Diff 420650.Apr 5 2022, 3:52 PM
kda marked 9 inline comments as done.

improve unit test (reading and edge cases), add sanitizer_common test, adjust implementation.

kda updated this revision to Diff 420655.Apr 5 2022, 4:23 PM

a few more adjustments

compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
2518

PTAL: I think I was seeing a side effect for 'strlen'. I think you were right the first time.

vitalybuka accepted this revision.Apr 8 2022, 12:50 PM
vitalybuka added inline comments.
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
2513

it's null-terminated string so +1

2518

I see, it writes past "res" in some cases, but it's not considered a part of output
so no +1 here.

This revision is now accepted and ready to land.Apr 8 2022, 12:50 PM
kda updated this revision to Diff 421644.Apr 8 2022, 3:00 PM

check trailing null byte of src parameter to pton.

kda marked an inline comment as done.Apr 8 2022, 3:00 PM
This revision was landed with ongoing or failed builds.Apr 8 2022, 3:22 PM
This revision was automatically updated to reflect the committed changes.