[ 
https://issues.apache.org/jira/browse/THRIFT-6212?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Jens Geyer reassigned THRIFT-6212:
----------------------------------

    Assignee: Jens Geyer

> Compiler loops forever on an unterminated comment at end of file
> ----------------------------------------------------------------
>
>                 Key: THRIFT-6212
>                 URL: https://issues.apache.org/jira/browse/THRIFT-6212
>             Project: Thrift
>          Issue Type: Bug
>          Components: Compiler (General)
>            Reporter: Jens Geyer
>            Assignee: Jens Geyer
>            Priority: Minor
>
> h2. Symptom
> A {{.thrift}} file whose last comment is never closed makes the compiler loop 
> forever instead of reporting an error:
> {code}
> $ printf '/* unterminated comment' > c.thrift
> $ thrift --gen cpp c.thrift        # never returns
> $ printf '/** unterminated doc'    > d.thrift
> $ thrift --gen cpp d.thrift        # never returns
> {code}
> Reproduced against master @ {{5c5e93e1e}} (the lexer is byte-identical to 
> {{59a949c80}}, where it was measured). Both invocations were still running 
> when a 10 second timeout killed them.
> h2. Cause
> Both comment scanners test {{yyinput()}} for {{EOF}}:
> {code}
>     int ch = yyinput();
>     parsed.push_back(ch);
>     switch (ch) {
>       case EOF:
>         yyerror("Unexpected end of file in multiline comment at %d\n", 
> yylineno);
>         exit(1);
> {code}
> flex's {{yyinput()}} returns {{0}} at end of input, never {{-1}}, and keeps 
> returning {{0}} on every subsequent call. Measured with a standalone flex 
> 2.6.4 scanner using this file's own options, with and without {{noyywrap}}. 
> So {{case EOF:}} never matches, the byte falls through to {{default:}}, 
> {{parsed.push_back(ch)}} appends a NUL, and the loop asks for one more 
> character forever, growing {{parsed}} without bound.
> Two sites in {{compiler/cpp/src/thrift/thriftl.ll}}:
> * line 136, the {{doctext_begin}} rule
> * line 179, the {{multicm_begin}} rule
> When the input comes from a memory buffer rather than a file there is no 
> {{yyin}}, and the loop reaches {{fread()}} on a null {{FILE*}} instead of 
> spinning:
> {code}
> #0  __GI__IO_fread (buf=..., size=1, count=3, fp=0x0) at ./libio/iofread.c:37
> #1  yy_get_next_buffer () at thriftl.cc:1708
> #2  yyinput () at thriftl.cc:1841
> {code}
> That path matters because the compiler test suite drives the lexer through 
> {{yy_scan_bytes()}}, so a test case for an unterminated comment takes the 
> whole suite down until this is fixed.
> h2. Relationship to THRIFT-4244
> The identical defect in the string-literal scanner is being fixed under 
> THRIFT-4244, which introduces a {{yywrap()}} callback and a flag that tells 
> real end of input from a literal NUL byte. The comment scanners were 
> deliberately left out of that pull request's scope.
> The fix here reuses that flag, so it depends on THRIFT-4244 landing first.
> h2. Proposed fix
> Replace {{case EOF:}} with {{case 0:}} guarded by the end-of-input flag, at 
> both sites:
> {code}
>    while(state < 2)
>    {
> +    yyinput_reached_eof = false;
>      int ch = yyinput();
>      parsed.push_back(ch);
>      switch (ch) {
> -      case EOF:
> -        yyerror("Unexpected end of file in multiline comment at %d\n", 
> yylineno);
> -        exit(1);
> +      case 0:
> +        if (yyinput_reached_eof) {
> +          yyerror("Unexpected end of file in multiline comment at %d\n", 
> yylineno);
> +          exit(1);
> +        }
> +        state = 0;
> +        break;
> {code}
> Guarding on the flag rather than treating every {{0}} as end of input keeps 
> the current behaviour for a literal NUL byte inside a closed comment, which 
> today lands in {{parsed}} and is either discarded ({{multicm_begin}}) or 
> truncated by {{strdup()}} ({{doctext_begin}}).
> Accepted input is unaffected either way: the change only reaches input that 
> never terminates today.
> h2. Scope
> Compiler only. The lexer is shared by every language binding, so no generator 
> changes are needed.
> This description was AI-assisted (Claude Opus 5); every claim above was 
> verified by execution against the named commits.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to