From 092e01962dfbe7db9f5e57ca365b8ca56b4aa96a Mon Sep 17 00:00:00 2001 From: Cary Coutant Date: Mon, 19 Dec 2016 19:19:46 -0800 Subject: [PATCH] Fix read-beyond-end-of-buffer error in script parsing. 2016-12-19 Cary Coutant gold/ PR gold/20949 * script.cc (Lex::get_token): Don't look ahead past NUL characters. --- gold/ChangeLog | 5 +++++ gold/script.cc | 35 +++++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index 3c89094da3c..ecd958f940a 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,8 @@ +2016-12-19 Cary Coutant + + PR gold/20949 + * script.cc (Lex::get_token): Don't look ahead past NUL characters. + 2016-12-19 Cary Coutant PR gold/14676 diff --git a/gold/script.cc b/gold/script.cc index bb8b4372f88..e4d0593cb0d 100644 --- a/gold/script.cc +++ b/gold/script.cc @@ -764,12 +764,6 @@ Lex::get_token(const char** pp) while (true) { - if (*p == '\0') - { - *pp = p; - return this->make_eof_token(p); - } - // Skip whitespace quickly. while (*p == ' ' || *p == '\t' || *p == '\r') ++p; @@ -782,8 +776,18 @@ Lex::get_token(const char** pp) continue; } + char c0 = *p; + + if (c0 == '\0') + { + *pp = p; + return this->make_eof_token(p); + } + + char c1 = p[1]; + // Skip C style comments. - if (p[0] == '/' && p[1] == '*') + if (c0 == '/' && c1 == '*') { int lineno = this->lineno_; int charpos = p - this->linestart_ + 1; @@ -797,7 +801,7 @@ Lex::get_token(const char** pp) } // Skip line comments. - if (*p == '#') + if (c0 == '#') { *pp = p + 1; if (!this->skip_line_comment(pp)) @@ -807,7 +811,7 @@ Lex::get_token(const char** pp) } // Check for a name. - if (this->can_start_name(p[0], p[1])) + if (this->can_start_name(c0, c1)) return this->gather_token(Token::TOKEN_STRING, &Lex::can_continue_name, p, p + 1, pp); @@ -820,35 +824,38 @@ Lex::get_token(const char** pp) return this->gather_quoted_string(pp); } + // Be careful not to lookahead past the end of the buffer. + char c2 = (c1 == '\0' ? '\0' : p[2]); + // Check for a number. - if (this->can_start_hex(p[0], p[1], p[2])) + if (this->can_start_hex(c0, c1, c2)) return this->gather_token(Token::TOKEN_INTEGER, &Lex::can_continue_hex, p, p + 3, pp); - if (Lex::can_start_number(p[0])) + if (Lex::can_start_number(c0)) return this->gather_token(Token::TOKEN_INTEGER, &Lex::can_continue_number, p, p + 1, pp); // Check for operators. - int opcode = Lex::three_char_operator(p[0], p[1], p[2]); + int opcode = Lex::three_char_operator(c0, c1, c2); if (opcode != 0) { *pp = p + 3; return this->make_token(opcode, p); } - opcode = Lex::two_char_operator(p[0], p[1]); + opcode = Lex::two_char_operator(c0, c1); if (opcode != 0) { *pp = p + 2; return this->make_token(opcode, p); } - opcode = Lex::one_char_operator(p[0]); + opcode = Lex::one_char_operator(c0); if (opcode != 0) { *pp = p + 1; -- 2.30.2