Hi, When passing an input of exactly 64 bytes to the idn tool it will generate an out of bounds stack read. This happens in the function idna_to_ascii_4i.
In Line 213 if the input is less than 64 bytes it will zero-terminate the string. However if it's exactly 64 bytes the input will fill the out buffer and no zero termination will happen. Therefore the strlen call in line 271 will cause an out of bounds. Attached a sample input and apatch that will return an error on a 64 byte input. The strlen (out) > 63 check doesn't really make sense, because inside a 64 byte buffer there can never be a correct zero-terminated string longer than 63 bytes. Therefore I've removed that check. Found with the help of american fuzzy lop. Address Sanitizer output: ==8591==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd6c39b5e0 at pc 0x7eff8b780e00 bp 0x7ffd6c39b420 sp 0x7ffd6c39b3f0 READ of size 66 at 0x7ffd6c39b5e0 thread T0 #0 0x7eff8b780dff in strlen (/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/libasan.so.1+0x32dff) #1 0x412220 in idna_to_ascii_4i /mnt/ram/libidn-1.31-vanilla/lib/idna.c:269 #2 0x4131fb in idna_to_ascii_4z /mnt/ram/libidn-1.31-vanilla/lib/idna.c:519 #3 0x403582 in main /mnt/ram/libidn-1.31-vanilla/src/idn.c:374 #4 0x7eff8b3d0f9f in __libc_start_main (/lib64/libc.so.6+0x1ff9f) #5 0x401c78 (/mnt/ram/libidn-1.31-vanilla/src/idn+0x401c78) Address 0x7ffd6c39b5e0 is located in stack of thread T0 at offset 96 in frame #0 0x412c10 in idna_to_ascii_4z /mnt/ram/libidn-1.31-vanilla/lib/idna.c:472 This frame has 1 object(s): [32, 96) 'buf' <== Memory access at offset 96 overflows this variable HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext (longjmp and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: stack-buffer-overflow ??:0 strlen Shadow bytes around the buggy address: 0x10002d86b660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10002d86b670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10002d86b680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10002d86b690: 00 00 00 00 f1 f1 f1 f1 00 f4 f4 f4 00 00 00 00 0x10002d86b6a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x10002d86b6b0: f1 f1 f1 f1 00 00 00 00 00 00 00 00[f3]f3 f3 f3 0x10002d86b6c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10002d86b6d0: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 0x10002d86b6e0: 00 f4 f4 f4 f2 f2 f2 f2 00 f4 f4 f4 f2 f2 f2 f2 0x10002d86b6f0: 00 f4 f4 f4 f2 f2 f2 f2 00 f4 f4 f4 f2 f2 f2 f2 0x10002d86b700: 00 f4 f4 f4 f2 f2 f2 f2 00 00 00 00 00 00 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Contiguous container OOB:fc ASan internal: fe -- Hanno Böck http://hboeck.de/ mail/jabber: ha...@hboeck.de GPG: BBB51E42
--- libidn-1.31-vanilla/lib/idna.c 2015-07-08 01:50:11.000000000 +0200 +++ libidn-1.31/lib/idna.c 2015-07-09 14:16:09.817985471 +0200 @@ -212,6 +212,8 @@ } if (i < 64) out[i] = '\0'; + else + return IDNA_INVALID_LENGTH; if (inasciirange) goto step8; } @@ -266,7 +268,7 @@ step8: free (src); - if (strlen (out) < 1 || strlen (out) > 63) + if (strlen (out) < 1) return IDNA_INVALID_LENGTH; return IDNA_SUCCESS;
libidn-oob-stack-read-idna_to_ascii_4i
Description: Binary data
pgpp7Hd1ScJtL.pgp
Description: OpenPGP digital signature
_______________________________________________ Help-libidn mailing list Help-libidn@gnu.org https://lists.gnu.org/mailman/listinfo/help-libidn