From patchwork Fri May 24 15:21:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom de Vries X-Patchwork-Id: 32850 Received: (qmail 120543 invoked by alias); 24 May 2019 15:21:10 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 120535 invoked by uid 89); 24 May 2019 15:21:10 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.1 spammy=terminating, Advance X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 24 May 2019 15:21:08 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 63900AF52; Fri, 24 May 2019 15:21:06 +0000 (UTC) Date: Fri, 24 May 2019 17:21:04 +0200 From: Tom de Vries To: gdb-patches@sourceware.org, Pedro Alves Subject: [PATCH][gdb] Fix dynamic-stack-buffer-overflow in linespec_lexer_lex_string Message-ID: <20190524152102.GA19370@delia> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.10.1 (2018-07-13) X-IsSubscribed: yes Hi, When compiling gdb with '-lasan -fsanitizer=address' and running tests with 'export ASAN_OPTIONS="detect_leaks=0:alloc_dealloc_mismatch=0"', I run into: ... ERROR: GDB process no longer exists UNRESOLVED: gdb.linespec/cpls-abi-tag.exp: \ test_abi_tag: completion: at tag: tab complete "b test_abi_tag_function[abi:" ... In more detail: ... ==3637==ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address \ 0x7fff5952bbdd at pc 0x000000fe5c57 bp 0x7fff5952af30 sp 0x7fff5952af28 READ of size 1 at 0x7fff5952bbdd thread T0 #0 0xfe5c56 in linespec_lexer_lex_string src/gdb/linespec.c:727 #1 0xfe7473 in linespec_lexer_lex_one src/gdb/linespec.c:946 #2 0xfe799d in linespec_lexer_consume_token src/gdb/linespec.c:982 #3 0xff446d in parse_linespec src/gdb/linespec.c:2564 #4 0xff78be in linespec_complete(completion_tracker&, char const*, \ symbol_name_match_type) src/gdb/linespec.c:2961 #5 0xb9299c in complete_address_and_linespec_locations \ src/gdb/completer.c:573 #6 0xb93e90 in location_completer(cmd_list_element*, completion_tracker&, \ char const*, char const*) src/gdb/completer.c:919 #7 0xb940c5 in location_completer_handle_brkchars src/gdb/completer.c:956 #8 0xb957ec in complete_line_internal_normal_command \ src/gdb/completer.c:1208 #9 0xb96507 in complete_line_internal_1 src/gdb/completer.c:1430 #10 0xb965c2 in complete_line_internal src/gdb/completer.c:1449 #11 0xb98630 in gdb_completion_word_break_characters_throw \ src/gdb/completer.c:1862 #12 0xb98838 in gdb_completion_word_break_characters() \ src/gdb/completer.c:1897 #13 0x16c6362 in _rl_find_completion_word src/readline/complete.c:943 #14 0x16ca8d0 in rl_complete_internal src/readline/complete.c:1843 #15 0x16c460c in rl_complete src/readline/complete.c:408 #16 0x16b3368 in _rl_dispatch_subseq src/readline/readline.c:774 #17 0x16b3092 in _rl_dispatch src/readline/readline.c:724 #18 0x16b2939 in readline_internal_char src/readline/readline.c:552 #19 0x16f1fb0 in rl_callback_read_char src/readline/callback.c:201 #20 0xddc5a1 in gdb_rl_callback_read_char_wrapper_noexcept \ src/gdb/event-top.c:175 #21 0xddc773 in gdb_rl_callback_read_char_wrapper src/gdb/event-top.c:192 #22 0xddd9f5 in stdin_event_handler(int, void*) src/gdb/event-top.c:514 #23 0xdd7d8f in handle_file_event src/gdb/event-loop.c:731 #24 0xdd8607 in gdb_wait_for_event src/gdb/event-loop.c:857 #25 0xdd629c in gdb_do_one_event() src/gdb/event-loop.c:321 #26 0xdd6344 in start_event_loop() src/gdb/event-loop.c:370 #27 0x10a7715 in captured_command_loop src/gdb/main.c:331 #28 0x10aa548 in captured_main src/gdb/main.c:1173 #29 0x10aa5d8 in gdb_main(captured_main_args*) src/gdb/main.c:1188 #30 0x87bd35 in main src/gdb/gdb.c:32 #31 0x7fb0364c6f89 in __libc_start_main (/lib64/libc.so.6+0x20f89) #32 0x87bb49 in _start (build/gdb/gdb+0x87bb49) Address 0x7fff5952bbdd is located in stack of thread T0 at offset 557 in frame #0 0xb93702 in location_completer(cmd_list_element*, completion_tracker&, \ char const*, char const*) src/gdb/completer.c:831 This frame has 4 object(s): [32, 40) 'copy' [96, 104) 'location' [160, 168) 'text' [224, 256) 'completion_info' <== Memory access at offset 557 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: dynamic-stack-buffer-overflow \ src/gdb/linespec.c:727 in linespec_lexer_lex_string Shadow bytes around the buggy address: 0x10006b29d720: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10006b29d730: 00 00 00 00 00 00 f1 f1 f1 f1 00 f2 f2 f2 f2 f2 0x10006b29d740: f2 f2 00 f2 f2 f2 f2 f2 f2 f2 00 f2 f2 f2 f2 f2 0x10006b29d750: f2 f2 00 00 00 00 f3 f3 f3 f3 00 00 00 00 00 00 0x10006b29d760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x10006b29d770: 00 00 00 00 ca ca ca ca 00 00 00[05]cb cb cb cb 0x10006b29d780: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 0x10006b29d790: 00 f2 f2 f2 f2 f2 f2 f2 00 f2 f2 f2 f3 f3 f3 f3 0x10006b29d7a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10006b29d7b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10006b29d7c0: 00 00 00 00 00 00 00 00 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 Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==3637==ABORTING ... The problem happens in linespec_lexer_lex_string when lexing "b test_abi_tag_function[abi:\0" (using a notation where we make the implicit terminating \0 explicit). We arrrive here with (PARSER_STREAM (parser)) == ":\0": ... /* Do not tokenize ABI tags such as "[abi:cxx11]". */ else if (PARSER_STREAM (parser) - start > 4 && startswith (PARSER_STREAM (parser) - 4, "[abi")) ++(PARSER_STREAM (parser)); ... and consume ':', after which we end up here and consume '\0': ... /* Advance the stream. */ ++(PARSER_STREAM (parser)); ... after which (PARSER_STREAM (parser)) points past the end of the string. Fix this by removing the first "++(PARSER_STREAM (parser))", and add an assert to the second one to detect moving past the end-of-string. Build and tested on x86_64-linux. OK for trunk? Thanks, - Tom [gdb] Fix dynamic-stack-buffer-overflow in linespec_lexer_lex_string gdb/ChangeLog: 2019-05-24 Tom de Vries PR gdb/24611 * linespec.c (linespec_lexer_lex_string): Remove incorrect "++(PARSER_STREAM (parser))" for "[abi"-prefixed colon. Add assert. --- gdb/linespec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gdb/linespec.c b/gdb/linespec.c index f418e03b77..d28c390f13 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -760,7 +760,7 @@ linespec_lexer_lex_string (linespec_parser *parser) /* Do not tokenize ABI tags such as "[abi:cxx11]". */ else if (PARSER_STREAM (parser) - start > 4 && startswith (PARSER_STREAM (parser) - 4, "[abi")) - ++(PARSER_STREAM (parser)); + ; /* Do not tokenify if the input length so far is one (i.e, a single-letter drive name) and the next character @@ -861,6 +861,7 @@ linespec_lexer_lex_string (linespec_parser *parser) } /* Advance the stream. */ + gdb_assert (*(PARSER_STREAM (parser)) != '\0'); ++(PARSER_STREAM (parser)); } }