I rewrote a bit of the first issue to better understand it, and also
provide a patch:
## 1. Integer Underflow in `raptor_uri_normalize_path()`
There's an integer underflow in a path length calculation in
`raptor_uri_normalize_path()`.
This can be triggered by running the PoC below:
```
utils/rapper -i turtle memcpy_int_underflow.poc
rapper: Parsing URI file:///memcpy_int_underflow.poc with parser turtle
rapper: Serializing with serializer ntriples
free(): invalid pointer
Aborted
```
With an ASAN build of `rapper` we can more clearly see the issue without
the need of a debugger:
```
raptor-asan/utils/rapper -i turtle memcpy_int_underflow.poc
rapper: Parsing URI file:///memcpy_int_underflow.poc with parser turtle
rapper: Serializing with serializer ntriples
=================================================================
==2406522==ERROR: AddressSanitizer: negative-size-param: (size=-5)
#0 0x5f90a3e1cf33 in __interceptor_memcpy
(/raptor/raptor-asan/utils/.libs/rapper+0x3cf33) (BuildId:
31b11a035fdbbfb23ddb7c1a5db60302956622be)
#1 0x7c902fa96e5a in raptor_uri_resolve_uri_reference
(/raptor/raptor/src/.libs/libraptor2.so.0+0x19e5a) (BuildId:
9edf75a105deaf007b9332b0a0367c8ad4af744d)
#2 0x7c902fa9741c in raptor_new_uri_relative_to_base_counted
(/raptor/raptor/src/.libs/libraptor2.so.0+0x1a41c) (BuildId:
9edf75a105deaf007b9332b0a0367c8ad4af744d)
#3 0x7c902fa9747a in raptor_new_uri_relative_to_base
(/raptor/raptor/src/.libs/libraptor2.so.0+0x1a47a) (BuildId:
9edf75a105deaf007b9332b0a0367c8ad4af744d)
#4 0x7c902fab93fc in turtle_lexer_lex
(/raptor/raptor/src/.libs/libraptor2.so.0+0x3c3fc) (BuildId:
9edf75a105deaf007b9332b0a0367c8ad4af744d)
#5 0x7c902fabc3ec in turtle_parser_parse
(/raptor/raptor/src/.libs/libraptor2.so.0+0x3f3ec) (BuildId:
9edf75a105deaf007b9332b0a0367c8ad4af744d)
#6 0x7c902fabebb9 in turtle_parse turtle_parser.c
#7 0x7c902fabf3ff in raptor_turtle_parse_chunk turtle_parser.c
#8 0x7c902fa92de4 in raptor_parser_parse_chunk
(/raptor/raptor/src/.libs/libraptor2.so.0+0x15de4) (BuildId:
9edf75a105deaf007b9332b0a0367c8ad4af744d)
#9 0x7c902fa92fc1 in raptor_parser_parse_file_stream
(/raptor/raptor/src/.libs/libraptor2.so.0+0x15fc1) (BuildId:
9edf75a105deaf007b9332b0a0367c8ad4af744d)
#10 0x7c902fa93174 in raptor_parser_parse_file
(/raptor/raptor/src/.libs/libraptor2.so.0+0x16174) (BuildId:
9edf75a105deaf007b9332b0a0367c8ad4af744d)
#11 0x5f90a3ed9492 in main
(/raptor/raptor-asan/utils/.libs/rapper+0xf9492) (BuildId:
31b11a035fdbbfb23ddb7c1a5db60302956622be)
#12 0x7c902f7816c9 in __libc_start_call_main
csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#13 0x7c902f781784 in __libc_start_main csu/../csu/libc-start.c:360:3
#14 0x5f90a3e01650 in _start
(/raptor/raptor-asan/utils/.libs/rapper+0x21650) (BuildId:
31b11a035fdbbfb23ddb7c1a5db60302956622be)
(...)
SUMMARY: AddressSanitizer: negative-size-param
(/raptor/raptor-asan/utils/.libs/rapper+0x3cf33) (BuildId:
31b11a035fdbbfb23ddb7c1a5db60302956622be) in __interceptor_memcpy
==2406522==ABORTING
```
The crash occurs because `raptor_uri_normalize_path()`, which does some
complicated jiggling to normalize paths, and fails to take into account
integer underflows. The function will not be shown here as it is quite
complex.
`raptor_uri_normalize_path()` is called from
`raptor_uri_resolve_uri_reference()` to normalize a path, and the crash
occurs in a juicy `memcpy()` inside `raptor_uri_resolve_uri_reference()`
(`raptor_rfc2396.c:664`) where `result.path_len` is the underflowed
integer (ASAN's `negative-size-param`), and `result.path` is attacker
controlled:
```c
if(result.path) {
memcpy(p, result.path, result.path_len);
p+= result.path_len;
}
```
The non-ASAN crash in `free()` shown at the top occurs in line 685:
```c
if(path_buffer)
RAPTOR_FREE(char*, path_buffer);
```
The fix, however, is rather simple! The function contains several of
these checks after each calculation:
```c
#if defined(RAPTOR_DEBUG)
if(path_len != strlen((const char*)path_buffer))
RAPTOR_FATAL3("Path length %ld does not match calculated %ld.",
(long)strlen((const char*)path_buffer), (long)path_len);
#endif
```
If we remove the `#if defined` / `#endif` around this code in lines 396
and 399, we get an error instead of a crash:
`raptor_rfc2396.c:397:raptor_uri_normalize_path: fatal error: Path
length 0 does not match calculated -5.Aborted`
### 1.1 Steps to reproduce
`rapper -i turtle memcpy_int_underflow.poc`
Contents of `memcpy_int_underflow.poc`:
```
@base <http:o/www.w3.org/2001/sw/DataA#cess/df1.ttl> .
@prefix bdf: <.&/../?D/../../1999/02/22-rdf-syntax-ns#>/dbpe
```
### 1.2 Patch
```diff
diff --git a/src/raptor_rfc2396.c b/src/raptor_rfc2396.c
index 89183d96..f58710c5 100644
--- a/src/raptor_rfc2396.c
+++ b/src/raptor_rfc2396.c
@@ -393,10 +393,8 @@ raptor_uri_normalize_path(unsigned char*
path_buffer, size_t path_len)
}
-#if defined(RAPTOR_DEBUG)
if(path_len != strlen((const char*)path_buffer))
RAPTOR_FATAL3("Path length %ld does not match calculated %ld.",
(long)strlen((const char*)path_buffer), (long)path_len);
-#endif
/* RFC3986 Appendix C.2 / 5.4.2 Abnormal Examples
* Remove leading /../ and /./
```
Regards,
Pedro