[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
PSPP-BUG: [bug #54664] segfault in count_newlines in lexer.c
From: |
Tianxiao Gu |
Subject: |
PSPP-BUG: [bug #54664] segfault in count_newlines in lexer.c |
Date: |
Tue, 18 Sep 2018 19:40:52 -0400 (EDT) |
User-agent: |
Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0 |
Follow-up Comment #1, bug #54664 (project pspp):
We found that token->token_len is used without initialization.
The struct `token` is created at line 1374.
By analyzing the code of `lex_push_token__`, we found that the memory of token
is allocated via `xnmalloc` in dequeu.c. So the memory may not be set to
zero.
Then, the following initialization code (line 1377, 1378, 1379, 1381, 1383)
does not set a proper value to `token->token_len`.
`token_len` is finally set to a proper value at 1457.
But in `lex_source_read__` (at line 1398), the toekn_len will be used during
reporting parsing error, which will lead to the crash.
1374 /* Append a new token to SRC and initialize it. */
1375 struct lex_token *token = lex_push_token__ (src);
1376 struct scanner scanner;
1377 scanner_init (&scanner, &token->token);
1378 token->line_pos = src->line_pos;
1379 token->token_pos = src->seg_pos;
1380 if (src->reader->line_number > 0)
1381 token->first_line = src->reader->line_number + src->n_newlines;
1382 else
1383 token->first_line = 0;
1384
1385 /* Extract segments and pass them through the scanner until we obtain
a
1386 token. */
1387 for (;;)
1388 {
1389 /* Extract a segment. */
1390 const char *segment = &src->buffer[state.seg_pos - src->tail];
1391 size_t seg_maxlen = src->head - state.seg_pos;
1392 enum segment_type type;
1393 int seg_len = segmenter_push (&state.segmenter, segment,
seg_maxlen,
1394 &type);
1395 if (seg_len < 0)
1396 {
1397 /* The segmenter needs more input to produce a segment. */
1398 lex_source_read__ (src);
1399 continue;
1400 }
1401
1402 /* Update state based on the segment. */
1403 state.last_segment = type;
1404 state.seg_pos += seg_len;
1405 if (type == SEG_NEWLINE)
1406 {
1407 state.newlines++;
1408 state.line_pos = state.seg_pos;
1409 }
1410
1411 /* Pass the segment into the scanner and try to get a token out.
*/
1412 enum scan_result result = scanner_push (&scanner, type,
1413 ss_buffer (segment,
seg_len),
1414 &token->token);
1415 if (result == SCAN_SAVE)
1416 saved = state;
1417 else if (result == SCAN_BACK)
1418 {
1419 state = saved;
1420 break;
1421 }
1422 else if (result == SCAN_DONE)
1423 break;
1424 }
1425
1426 /* If we've reached the end of a line, or the end of a command, then
pass
1427 the line to the output engine as a syntax text item. */
1428 int n_lines = state.newlines;
1429 if (state.last_segment == SEG_END_COMMAND &&
!src->suppress_next_newline)
1430 {
1431 n_lines++;
1432 src->suppress_next_newline = true;
1433 }
1434 else if (n_lines > 0 && src->suppress_next_newline)
1435 {
1436 n_lines--;
1437 src->suppress_next_newline = false;
1438 }
1439 for (int i = 0; i < n_lines; i++)
1440 {
1441 const char *line = &src->buffer[src->journal_pos - src->tail];
1442 const char *newline = rawmemchr (line, '\n');
1443 size_t line_len = newline - line;
1444 if (line_len > 0 && line[line_len - 1] == '\r')
1445 line_len--;
1446
1447 char *syntax = malloc (line_len + 2);
1448 memcpy (syntax, line, line_len);
1449 syntax[line_len] = '\n';
1450 syntax[line_len + 1] = '\0';
1451
1452 text_item_submit (text_item_create_nocopy (TEXT_ITEM_SYNTAX,
syntax));
1453
1454 src->journal_pos += newline - line + 1;
1455 }
1456
1457 token->token_len = state.seg_pos - src->seg_pos;
_______________________________________________________
Reply to this item at:
<https://savannah.gnu.org/bugs/?54664>
_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/