Bison解析器执行根据输入文件大小终止

时间:2014-08-11 05:20:27

标签: windows bison filesize terminate

我使用flex创建了一个使用bison和scanner的解析器来解析windows中的setupapi.log文件。我尝试通过获取文件的一小部分来执行解析器并完成。它适用于大约20行的文件。但是当我在身体的最后一行添加两个单词时,它终止了那里,因为.exe已经停止工作而给出了错误。

我怎样摆脱这个。

我在我的bison文件中使用%union,只要遇到标识符,就会使用flexoc文件中的malloc分配内存。

我的flex文件是:

%{  
 #include <stdio.h>
#include "check.tab.h"
#include <string.h>
 #include<malloc.h>
int yyline=1;
 int i;

%}



identifier      [_a-zA-Z\.0-9:=&\\{}()\'\-]+
time            ([0-9]+\:[0-9]+\:[0-9]+\.[0-9]+)

%%

"/"         {
            return(SLASH_TOK);
         }

"["         {
            return(OPEN_TOK);
         }

"]"         {
            return(CLOSE_TOK);
         }

">>>"       {
            return (START_TOK); 
        }

"<<<"       {
            return (END_TOK);
         }

"!!!"       {
            return(ERROR_TOK);
         }

  "!"           {
                return(WARN_TOK);
                }

   "...:"       {
                    return(VEND_INFO);
                }

   "bak:"       {
                    return(BAK_TOK);
                }

   "cci:"       {
                    return(CCI_TOK);
                }   



         //SOME MORE TOKENS ARE HERE....


"\n"        {
            yyline++;
        }

{time}      {
           yylval.sval = malloc(strlen(yytext)+1);
           printf("FRM LEXER TIME= %s %s\n",yytext,yylval.sval);
           strncpy(yylval.sval,yytext,strlen(yytext)+1);

            for(i=0;yylval.sval[i]!='\0';i++)
                 {
                        if(!(i<strlen(yytext)))
                        {
                         yylval.sval[i]='\0';
                        }
                }

                printf("FRM LEXER TIME= %s %s\n",yytext,yylval.sval);
                 return(TIME);
        }


[a-zA-Z_0-9:\\]+(\.)+[\.a-zA-Z_0-9:\\]* {printf("REACHED EXTRA\n");return(DATA);}


[a-zA-Z]+(\:)+[\.a-zA-Z_0-9:\\]*    {yylval.sval = malloc(strlen(yytext)+1);
                strncpy(yylval.sval,yytext,strlen(yytext)+1);
                printf("REACHED EXTRA\n");
                 for(i=0;yylval.sval[i]!='\0';i++)
                 {
                        if(!(i<strlen(yytext)))
                        {
                         yylval.sval[i]='\0';
                        }
                }
                return(DATA);
             }

{identifier}    {

                yylval.sval = malloc(strlen(yytext)+1);
                strncpy(yylval.sval,yytext,strlen(yytext)+1);
                //printf("YYTEXT=%s %d\n",yytext,strlen(yytext));

                for(i=0;yylval.sval[i]!='\0';i++)
                {
                        if(!(i<strlen(yytext)))
                        {
                         yylval.sval[i]='\0';
                        }
                }

                printf("FRM LEXER ID = %s %s\n",yytext,yylval.sval);
                return(IDENTIFIER);
             }

%%

int yywrap(void)
{
return 1;
}

我的野牛文件是:

%{

#include <stdio.h>
#include <string.h>

extern int yyline;
extern char* yytext;
FILE *fp;
%}

%union
{
    char *sval;
};

%token  SLASH_TOK   
 %token      OPEN_TOK
 %token     CLOSE_TOK 
 %token     START_TOK   
    //ALL TOKENS ARE HERE


%type <sval> boot_data description statements word date section_title time_stamp section_body log_entry evt_catgry evt_time


%start session
%%

session : boot_data section
        {
        printf("SESSION\n");
        fprintf(fp,"NO.OF LINES PARSED = %d\n",yyline);
    }
    ;

boot_data : description statements description boot_time
    {
            printf("BOOT DATA\n");
            fprintf(fp,"DESCRIPTION:%s\n",$1);
    }
     ;

description : OPEN_TOK statements CLOSE_TOK
    {
        $$=$2;
        printf("DESCRIPTION\n");
    }
    ;

boot_time: OPEN_TOK statements date TIME CLOSE_TOK
    {
        printf("BOOT TIME\n");
        fprintf(fp,"DATE:%s\n",$3);
        fprintf(fp,"TIME:%s\n",$4);
    }
    ;

date : IDENTIFIER SLASH_TOK IDENTIFIER SLASH_TOK IDENTIFIER
    {
        printf("DATE\n");
        $$=$1;
        strcat($$,"/");
        strcat($$,$3);
        strcat($$,"/");
        strcat($$,$5);
    }
     ;

statements : word
     {
            $$=$1;
            printf("STAETEMENT 1\n");
    }

    |statements word

    {

            $$=$1;
            strcat($$," ");
            strcat($$,$2);
            printf("statements 2\n");
    }
    ;

word : IDENTIFIER
    {
        printf("WORD=%s  %s\n",yytext, $$);

    } 
    |TIME
    {
         printf("TIME=%s  %s\n",yytext, $$);
         fprintf(fp,"%s",$$);

    }
    |DATA
     ;

section : section_head section_body section_tail

     {
            printf("Compilation_start\n");
    }

    ;

section_head : section_title time_stamp
    {
            printf("Compilation_start111\n");
     }
     ;

section_title :START_TOK OPEN_TOK statements CLOSE_TOK
    {
            printf("Compilation_start222\n");
            fprintf(fp,"%s\n",$3);
     }
      ;

time_stamp :START_TOK statements date TIME
    {
            printf("Compilation_start444\n");
            fprintf(fp,"%s Date: %s\n",$2,$3);
            fprintf(fp,"%s Time: %s\n\n",$2,$4);
    }
    ;


section_body :log_entry
        {
        printf("single  entry\n");

       }

      |section_body log_entry
     {
        printf("MULTIPLE ENTRIES\n");            
     }
     ;

log_entry :entry_prefix evt_time evt_catgry statements
    {
                    printf("no time stamp\n");  
                   // fprintf(fp,"====%s====\n",$3);
                    }
    ;




section_tail :section_foot exit_status 
    {
            printf("Compilation_start666\n");
    }
      ;

section_foot:  END_TOK statements date TIME
    {
            printf("Compilation_start777\n");
            fprintf(fp,"\n\n%s Date: %s\n",$2,$3);
            fprintf(fp,"%s Time: %s\n",$2,$4);
    }
    ;

 exit_status : END_TOK OPEN_TOK statements CLOSE_TOK
    {
            printf("Compilation_start888\n");
            fprintf(fp,"\n%s\n",$3);
    }
    ;


%%

yyerror(char *str)
{
printf("Parse error: %s at line %d ,",str,yyline);
yywhere(); 
}

yywhere()
{   
int colon=0;
int i;
if(yytext) 
{ 
    for(i=0;i<50;i++) if(!yytext[i] || yytext[i] == '\n') break;
    if(i)
    {  
        if(!colon)  
        { 
            printf(" near: \"%s\"\n",  yytext);
            colon = 1; 
        }
    }  
    printf("\n");
}  
}   

int main(void) 
{
int i =remove("output.txt");
fp=fopen("output.txt","a+");

yyparse();
fclose(fp);
}

1 个答案:

答案 0 :(得分:2)

来自strcat手册页的

(对Windows也应该有效):

  

strcat()函数将src字符串追加到dest字符串,   在dest的末尾覆盖空字节(&#39; \ 0&#39;)然后   添加一个终止空字节。字符串   可能不会重叠,并且dest字符串必须有足够的空间用于结果。

现在你正在做:

statements : word
     {
            $$=$1;
            printf("STAETEMENT 1\n");
    }

    |statements word    
    {

            $$=$1;
            strcat($$," ");
            strcat($$,$2);
            printf("statements 2\n");
    }
    ;

因此,如果我假设您输入了两个单词,则会发生以下情况:

在第一个单词之后,语句指向此单词,因为您执行$$ = $1。 然后你的扫描仪会读取下一个单词,然后将空白和下一个单词连接到第一个单词。但是你没有采取有关可用内存的预防措施。 你用C编程,这意味着你必须自己做所有事情。

您可以将第二个操作更改为:

statements : statements word
     {
            int lgth1 = strlen($$);
            int lgth2 = strlen($2);
            /* instead of malloc you could also realloc */
            char *tmp = (char *) malloc((lgth1 + lgth2 + 1 + 1) * sizeof(char));
            /* no error handling for clarity */
            sprintf(tmp, "%s %s", $$, $2); /* alternative: strcpy(); strcat(); strcat(); */
            free($$); free($2); /* freeing the memory not used any more */
            $$ = tmp;
    }

这当然不是防弹代码,你也必须修理其他地方。 希望这会有所帮助。