[Forensics-changes] [yara] 93/415: Prevent malicious rules from causing memory corruption.
Hilko Bengen
bengen at moszumanska.debian.org
Thu Apr 3 05:42:49 UTC 2014
This is an automated email from the git hooks/post-receive script.
bengen pushed a commit to branch debian
in repository yara.
commit 079e89161167f007a5ab43dccede671f93f8bb83
Author: Mike Wiacek <mjwiacek at google.com>
Date: Sat Mar 26 19:32:38 2011 +0000
Prevent malicious rules from causing memory corruption.
---
libyara/lex.c | 938 ++++++++++++++++++++++++++++--------------------------
libyara/lex.l | 845 ++++++++++++++++++++++++------------------------
libyara/libyara.c | 19 +-
libyara/yara.h | 7 +-
4 files changed, 934 insertions(+), 875 deletions(-)
diff --git a/libyara/lex.c b/libyara/lex.c
index c00c813..155b6c0 100644
--- a/libyara/lex.c
+++ b/libyara/lex.c
@@ -53,7 +53,6 @@ typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
/* Limits of integral types. */
#ifndef INT8_MIN
@@ -84,6 +83,8 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#endif /* ! C99 */
+
#endif /* ! FLEXINT_H */
#ifdef __cplusplus
@@ -157,7 +158,15 @@ typedef void* yyscan_t;
/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
#endif
/* The state buf must be large enough to hold one state per character in the main buffer.
@@ -169,11 +178,6 @@ typedef void* yyscan_t;
typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2
@@ -209,6 +213,11 @@ typedef size_t yy_size_t;
#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
#ifndef YY_STRUCT_YY_BUFFER_STATE
#define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state
@@ -226,7 +235,7 @@ struct yy_buffer_state
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
- yy_size_t yy_n_chars;
+ int yy_n_chars;
/* Whether we "own" the buffer - i.e., we know we created it,
* and can realloc() it to grow it, and should free() it to
@@ -305,7 +314,7 @@ static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
void *yyalloc (yy_size_t ,yyscan_t yyscanner );
void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
@@ -630,24 +639,33 @@ static yyconst flex_int32_t yy_rule_can_match_eol[75] =
#include "lex.h"
#include "yara.h"
-#define YYTEXT_TO_BUFFER { \
- char *yptr = yytext; \
- while ( *yptr ) \
- { \
- *yyextra->lex_buf_ptr++ = *yptr++; \
- yyextra->lex_buf_len++; \
- } \
- }
-
+#define LEX_CHECK_SPACE_OK(data, current_size, max_length) \
+ if (strlen(data) + current_size >= max_length - 1) \
+ { \
+ yyerror(yyscanner, "out of space in lex_buf"); \
+ yyterminate(); \
+ }
+
+#define YYTEXT_TO_BUFFER \
+ { \
+ char *yptr = yytext; \
+ LEX_CHECK_SPACE_OK(yptr, yyextra->lex_buf_len, LEX_BUF_SIZE); \
+ while ( *yptr ) \
+ { \
+ *yyextra->lex_buf_ptr++ = *yptr++; \
+ yyextra->lex_buf_len++; \
+ } \
+ }
+
#ifdef WIN32
#define snprintf _snprintf
#endif
-
+
#define YY_NO_UNISTD_H 1
-#line 651 "lex.c"
+#line 669 "lex.c"
#define INITIAL 0
#define str 1
@@ -679,8 +697,8 @@ struct yyguts_t
size_t yy_buffer_stack_max; /**< capacity of stack. */
YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
char yy_hold_char;
- yy_size_t yy_n_chars;
- yy_size_t yyleng_r;
+ int yy_n_chars;
+ int yyleng_r;
char *yy_c_buf_p;
int yy_init;
int yy_start;
@@ -733,7 +751,7 @@ FILE *yyget_out (yyscan_t yyscanner );
void yyset_out (FILE * out_str ,yyscan_t yyscanner );
-yy_size_t yyget_leng (yyscan_t yyscanner );
+int yyget_leng (yyscan_t yyscanner );
char *yyget_text (yyscan_t yyscanner );
@@ -779,7 +797,12 @@ static int input (yyscan_t yyscanner );
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
#endif
/* Copy whatever the last rule matched to the standard output. */
@@ -787,7 +810,7 @@ static int input (yyscan_t yyscanner );
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
-#define ECHO fwrite( yytext, yyleng, 1, yyout )
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
#endif
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
@@ -798,7 +821,7 @@ static int input (yyscan_t yyscanner );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
- yy_size_t n; \
+ size_t n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -883,10 +906,10 @@ YY_DECL
register int yy_act;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-#line 47 "lex.l"
+#line 55 "lex.l"
-#line 890 "lex.c"
+#line 913 "lex.c"
yylval = yylval_param;
@@ -985,612 +1008,621 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
YY_RULE_SETUP
-#line 49 "lex.l"
-{ return _LT_; }
+#line 57 "lex.l"
+{ return _LT_; }
YY_BREAK
case 2:
YY_RULE_SETUP
-#line 50 "lex.l"
-{ return _GT_; }
+#line 58 "lex.l"
+{ return _GT_; }
YY_BREAK
case 3:
YY_RULE_SETUP
-#line 51 "lex.l"
-{ return _LE_; }
+#line 59 "lex.l"
+{ return _LE_; }
YY_BREAK
case 4:
YY_RULE_SETUP
-#line 52 "lex.l"
-{ return _GE_; }
+#line 60 "lex.l"
+{ return _GE_; }
YY_BREAK
case 5:
YY_RULE_SETUP
-#line 53 "lex.l"
-{ return _EQ_; }
+#line 61 "lex.l"
+{ return _EQ_; }
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 54 "lex.l"
-{ return _NEQ_; }
+#line 62 "lex.l"
+{ return _NEQ_; }
YY_BREAK
case 7:
YY_RULE_SETUP
-#line 55 "lex.l"
-{ return _PRIVATE_; }
+#line 63 "lex.l"
+{ return _PRIVATE_; }
YY_BREAK
case 8:
YY_RULE_SETUP
-#line 56 "lex.l"
-{ return _GLOBAL_; }
+#line 64 "lex.l"
+{ return _GLOBAL_; }
YY_BREAK
case 9:
YY_RULE_SETUP
-#line 57 "lex.l"
-{ return _RULE_; }
+#line 65 "lex.l"
+{ return _RULE_; }
YY_BREAK
case 10:
YY_RULE_SETUP
-#line 58 "lex.l"
-{ return _META_; }
+#line 66 "lex.l"
+{ return _META_; }
YY_BREAK
case 11:
YY_RULE_SETUP
-#line 59 "lex.l"
-{ return _STRINGS_; }
+#line 67 "lex.l"
+{ return _STRINGS_; }
YY_BREAK
case 12:
YY_RULE_SETUP
-#line 60 "lex.l"
-{ return _ASCII_; }
+#line 68 "lex.l"
+{ return _ASCII_; }
YY_BREAK
case 13:
YY_RULE_SETUP
-#line 61 "lex.l"
-{ return _WIDE_; }
+#line 69 "lex.l"
+{ return _WIDE_; }
YY_BREAK
case 14:
YY_RULE_SETUP
-#line 62 "lex.l"
-{ return _FULLWORD_; }
+#line 70 "lex.l"
+{ return _FULLWORD_; }
YY_BREAK
case 15:
YY_RULE_SETUP
-#line 63 "lex.l"
-{ return _NOCASE_; }
+#line 71 "lex.l"
+{ return _NOCASE_; }
YY_BREAK
case 16:
YY_RULE_SETUP
-#line 64 "lex.l"
-{ return _CONDITION_; }
+#line 72 "lex.l"
+{ return _CONDITION_; }
YY_BREAK
case 17:
YY_RULE_SETUP
-#line 65 "lex.l"
-{ return _TRUE_; }
+#line 73 "lex.l"
+{ return _TRUE_; }
YY_BREAK
case 18:
YY_RULE_SETUP
-#line 66 "lex.l"
-{ return _FALSE_; }
+#line 74 "lex.l"
+{ return _FALSE_; }
YY_BREAK
case 19:
YY_RULE_SETUP
-#line 67 "lex.l"
-{ return _NOT_; }
+#line 75 "lex.l"
+{ return _NOT_; }
YY_BREAK
case 20:
YY_RULE_SETUP
-#line 68 "lex.l"
-{ return _AND_; }
+#line 76 "lex.l"
+{ return _AND_; }
YY_BREAK
case 21:
YY_RULE_SETUP
-#line 69 "lex.l"
-{ return _OR_; }
+#line 77 "lex.l"
+{ return _OR_; }
YY_BREAK
case 22:
YY_RULE_SETUP
-#line 70 "lex.l"
-{ return _AT_; }
+#line 78 "lex.l"
+{ return _AT_; }
YY_BREAK
case 23:
YY_RULE_SETUP
-#line 71 "lex.l"
-{ return _IN_; }
+#line 79 "lex.l"
+{ return _IN_; }
YY_BREAK
case 24:
YY_RULE_SETUP
-#line 72 "lex.l"
-{ return _OF_; }
+#line 80 "lex.l"
+{ return _OF_; }
YY_BREAK
case 25:
YY_RULE_SETUP
-#line 73 "lex.l"
-{ return _THEM_; }
+#line 81 "lex.l"
+{ return _THEM_; }
YY_BREAK
case 26:
YY_RULE_SETUP
-#line 74 "lex.l"
-{ return _FOR_; }
+#line 82 "lex.l"
+{ return _FOR_; }
YY_BREAK
case 27:
YY_RULE_SETUP
-#line 75 "lex.l"
-{ return _ALL_; }
+#line 83 "lex.l"
+{ return _ALL_; }
YY_BREAK
case 28:
YY_RULE_SETUP
-#line 76 "lex.l"
-{ return _ANY_; }
+#line 84 "lex.l"
+{ return _ANY_; }
YY_BREAK
case 29:
YY_RULE_SETUP
-#line 77 "lex.l"
-{ return _ENTRYPOINT_; }
+#line 85 "lex.l"
+{ return _ENTRYPOINT_; }
YY_BREAK
case 30:
YY_RULE_SETUP
-#line 78 "lex.l"
-{ return _SIZE_; }
+#line 86 "lex.l"
+{ return _SIZE_; }
YY_BREAK
case 31:
YY_RULE_SETUP
-#line 79 "lex.l"
-{ return _RVA_; }
+#line 87 "lex.l"
+{ return _RVA_; }
YY_BREAK
case 32:
YY_RULE_SETUP
-#line 80 "lex.l"
-{ return _OFFSET_; }
+#line 88 "lex.l"
+{ return _OFFSET_; }
YY_BREAK
case 33:
YY_RULE_SETUP
-#line 81 "lex.l"
-{ return _FILE_; }
+#line 89 "lex.l"
+{ return _FILE_; }
YY_BREAK
case 34:
YY_RULE_SETUP
-#line 82 "lex.l"
-{ return _SECTION_; }
+#line 90 "lex.l"
+{ return _SECTION_; }
YY_BREAK
case 35:
YY_RULE_SETUP
-#line 83 "lex.l"
-{ return _UINT8_; }
+#line 91 "lex.l"
+{ return _UINT8_; }
YY_BREAK
case 36:
YY_RULE_SETUP
-#line 84 "lex.l"
-{ return _UINT16_; }
+#line 92 "lex.l"
+{ return _UINT16_; }
YY_BREAK
case 37:
YY_RULE_SETUP
-#line 85 "lex.l"
-{ return _UINT32_; }
+#line 93 "lex.l"
+{ return _UINT32_; }
YY_BREAK
case 38:
YY_RULE_SETUP
-#line 86 "lex.l"
-{ return _INT8_; }
+#line 94 "lex.l"
+{ return _INT8_; }
YY_BREAK
case 39:
YY_RULE_SETUP
-#line 87 "lex.l"
-{ return _INT16_; }
+#line 95 "lex.l"
+{ return _INT16_; }
YY_BREAK
case 40:
YY_RULE_SETUP
-#line 88 "lex.l"
-{ return _INT32_; }
+#line 96 "lex.l"
+{ return _INT32_; }
YY_BREAK
case 41:
YY_RULE_SETUP
-#line 89 "lex.l"
+#line 97 "lex.l"
{ return _MATCHES_; }
YY_BREAK
case 42:
YY_RULE_SETUP
-#line 90 "lex.l"
+#line 98 "lex.l"
{ return _CONTAINS_; }
YY_BREAK
case 43:
YY_RULE_SETUP
-#line 91 "lex.l"
-{ return _INDEX_; }
+#line 99 "lex.l"
+{ return _INDEX_; }
YY_BREAK
case 44:
/* rule 44 can match eol */
YY_RULE_SETUP
-#line 95 "lex.l"
+#line 102 "lex.l"
{ /* skip comments */ }
YY_BREAK
case 45:
YY_RULE_SETUP
-#line 97 "lex.l"
+#line 104 "lex.l"
{ /* skip single-line comments */ }
YY_BREAK
case 46:
YY_RULE_SETUP
-#line 99 "lex.l"
+#line 106 "lex.l"
{
- yyextra->lex_buf_ptr = yyextra->lex_buf;
- yyextra->lex_buf_len = 0;
- BEGIN(include);
- }
+ yyextra->lex_buf_ptr = yyextra->lex_buf;
+ yyextra->lex_buf_len = 0;
+ BEGIN(include);
+ }
YY_BREAK
case 47:
/* rule 47 can match eol */
YY_RULE_SETUP
-#line 105 "lex.l"
+#line 112 "lex.l"
{
- YYTEXT_TO_BUFFER;
- }
+ YYTEXT_TO_BUFFER;
+ }
YY_BREAK
case 48:
YY_RULE_SETUP
-#line 109 "lex.l"
-{
- char buffer[1024];
- char *current_file_name;
- char *s = NULL;
- char *b = NULL;
- char *f;
- FILE* fh;
- YARA_CONTEXT* context = yyget_extra(yyscanner);
-
- if (context->allow_includes)
- {
- *yyextra->lex_buf_ptr = '\0'; // null-terminate included file path
-
- // move path of current source file into buffer
-
- current_file_name = yr_get_current_file_name(context);
-
- if (current_file_name != NULL)
- {
- strncpy(buffer, yr_get_current_file_name(context), sizeof(buffer));
- }
- else
- {
- buffer[0] = '\0';
- }
-
- // make included file path relative to current source file
-
- s = strrchr(buffer, '/');
-
- #ifdef WIN32
- b = strrchr(buffer, '\\'); // in Windows both path delimiters are accepted
- #endif
-
- if (s != NULL || b != NULL)
- {
- f = (b > s)? (b + 1): (s + 1);
-
- strncpy(f, yyextra->lex_buf, sizeof(buffer) - (f - buffer));
-
- fh = fopen(buffer, "r");
-
- // if include file was not found relative to current source file, try to open it
- // with path as specified by user (maybe user wrote a full path)
-
- if (fh == NULL)
- {
- fh = fopen(yyextra->lex_buf, "r");
- }
- }
- else
- {
- fh = fopen(yyextra->lex_buf, "r");
- }
-
- if (fh != NULL)
- {
- if (yr_push_file_name(context, yyextra->lex_buf) == ERROR_INCLUDES_CIRCULAR_REFERENCE)
- {
- yyerror(yyscanner, "includes circular reference");
- yyterminate();
- }
-
- yypush_buffer_state(yy_create_buffer(fh,YY_BUF_SIZE,yyscanner),yyscanner);
- }
- else
- {
- snprintf(buffer, sizeof(buffer), "can't open include file: %s", yyextra->lex_buf);
- yyerror(yyscanner, buffer);
- }
-
- }
- else // not allowing includes
- {
- yyerror(yyscanner, "includes are disabled");
- yyterminate();
- }
-
- BEGIN(INITIAL);
- }
+#line 116 "lex.l"
+{
+ char buffer[1024];
+ char *current_file_name;
+ char *s = NULL;
+ char *b = NULL;
+ char *f;
+ FILE* fh;
+ YARA_CONTEXT* context = yyget_extra(yyscanner);
+
+ if (context->allow_includes)
+ {
+ *yyextra->lex_buf_ptr = '\0'; // null-terminate included file path
+
+ // move path of current source file into buffer
+ current_file_name = yr_get_current_file_name(context);
+
+ if (current_file_name != NULL)
+ {
+ strncpy(buffer, yr_get_current_file_name(context), sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ }
+ else
+ {
+ buffer[0] = '\0';
+ }
+
+ // make included file path relative to current source file
+ s = strrchr(buffer, '/');
+
+ #ifdef WIN32
+ b = strrchr(buffer, '\\'); // in Windows both path delimiters are accepted
+ #endif
+
+ if (s != NULL || b != NULL)
+ {
+ f = (b > s)? (b + 1): (s + 1);
+
+ strncpy(f, yyextra->lex_buf, sizeof(buffer) - (f - buffer));
+ buffer[sizeof(buffer)-1] = '\0';
+
+ // SECURITY: Potential for directory traversal here.
+ fh = fopen(buffer, "r");
+
+ // if include file was not found relative to current source file, try to open it
+ // with path as specified by user (maybe user wrote a full path)
+ if (fh == NULL)
+ {
+ // SECURITY: Potential for directory traversal here.
+ fh = fopen(yyextra->lex_buf, "r");
+ }
+ }
+ else
+ {
+ // SECURITY: Potential for directory traversal here.
+ fh = fopen(yyextra->lex_buf, "r");
+ }
+
+ if (fh != NULL)
+ {
+ int error_code = ERROR_SUCCESS;
+ if ((error_code = yr_push_file_name(context, yyextra->lex_buf)) != ERROR_SUCCESS)
+ {
+ if (error_code == ERROR_INCLUDES_CIRCULAR_REFERENCE)
+ {
+ yyerror(yyscanner, "includes circular reference");
+ }
+ else if (error_code == ERROR_INCLUDE_DEPTH_EXCEEDED)
+ {
+ yyerror(yyscanner, "includes circular reference");
+ }
+ yyterminate();
+ }
+ yypush_buffer_state(yy_create_buffer(fh,YY_BUF_SIZE,yyscanner),yyscanner);
+ }
+ else
+ {
+ snprintf(buffer, sizeof(buffer), "can't open include file: %s", yyextra->lex_buf);
+ yyerror(yyscanner, buffer);
+ }
+ }
+ else // not allowing includes
+ {
+ yyerror(yyscanner, "includes are disabled");
+ yyterminate();
+ }
+
+ BEGIN(INITIAL);
+ }
YY_BREAK
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(str):
case YY_STATE_EOF(regexp):
case YY_STATE_EOF(include):
-#line 190 "lex.l"
-{
- YARA_CONTEXT* context = yyget_extra(yyscanner);
-
- yr_pop_file_name(context);
-
- yypop_buffer_state(yyscanner);
-
- if ( !YY_CURRENT_BUFFER )
- {
- yyterminate();
- }
- }
+#line 205 "lex.l"
+{
+ YARA_CONTEXT* context = yyget_extra(yyscanner);
+
+ yr_pop_file_name(context);
+
+ yypop_buffer_state(yyscanner);
+
+ if (!YY_CURRENT_BUFFER)
+ {
+ yyterminate();
+ }
+ }
YY_BREAK
case 49:
YY_RULE_SETUP
-#line 204 "lex.l"
+#line 219 "lex.l"
{
- yylval->c_string = (char*) yr_strdup(yytext);
- return _STRING_IDENTIFIER_WITH_WILDCARD_;
- }
+ yylval->c_string = (char*) yr_strdup(yytext);
+ return _STRING_IDENTIFIER_WITH_WILDCARD_;
+ }
YY_BREAK
case 50:
YY_RULE_SETUP
-#line 209 "lex.l"
+#line 224 "lex.l"
{
- yylval->c_string = (char*) yr_strdup(yytext);
- return _STRING_IDENTIFIER_;
- }
+ yylval->c_string = (char*) yr_strdup(yytext);
+ return _STRING_IDENTIFIER_;
+ }
YY_BREAK
case 51:
YY_RULE_SETUP
-#line 215 "lex.l"
-{
- yylval->c_string = (char*) yr_strdup(yytext);
- yylval->c_string[0] = '$'; /* replace # by $*/
- return _STRING_COUNT_;
- }
+#line 230 "lex.l"
+{
+ yylval->c_string = (char*) yr_strdup(yytext);
+ yylval->c_string[0] = '$'; /* replace # by $*/
+ return _STRING_COUNT_;
+ }
YY_BREAK
case 52:
YY_RULE_SETUP
-#line 221 "lex.l"
-{
- yylval->c_string = (char*) yr_strdup(yytext);
- yylval->c_string[0] = '$'; /* replace @ by $*/
- return _STRING_OFFSET_;
- }
+#line 236 "lex.l"
+{
+ yylval->c_string = (char*) yr_strdup(yytext);
+ yylval->c_string[0] = '$'; /* replace @ by $*/
+ return _STRING_OFFSET_;
+ }
YY_BREAK
case 53:
YY_RULE_SETUP
-#line 227 "lex.l"
-{
- if (strlen(yytext) > 128)
- {
- yyerror(yyscanner, "indentifier too long");
- }
-
- yylval->c_string = (char*) yr_strdup(yytext);
- return _IDENTIFIER_;
- }
+#line 242 "lex.l"
+{
+ if (strlen(yytext) > 128)
+ {
+ yyerror(yyscanner, "indentifier too long");
+ }
+
+ yylval->c_string = (char*) yr_strdup(yytext);
+ return _IDENTIFIER_;
+ }
YY_BREAK
case 54:
YY_RULE_SETUP
-#line 237 "lex.l"
-{
- yylval->integer = (size_t) atol(yytext);
-
- if (strstr(yytext, "KB") != NULL)
- {
- yylval->integer *= 1024;
- }
- else if (strstr(yytext, "MB") != NULL)
- {
- yylval->integer *= 1048576;
- }
-
- return _NUMBER_;
- }
+#line 252 "lex.l"
+{
+ yylval->integer = (size_t) atol(yytext);
+
+ if (strstr(yytext, "KB") != NULL)
+ {
+ yylval->integer *= 1024;
+ }
+ else if (strstr(yytext, "MB") != NULL)
+ {
+ yylval->integer *= 1048576;
+ }
+ return _NUMBER_;
+ }
YY_BREAK
case 55:
YY_RULE_SETUP
-#line 252 "lex.l"
+#line 266 "lex.l"
{
- yylval->integer = xtoi(yytext + 2);
- return _NUMBER_;
- }
+ yylval->integer = xtoi(yytext + 2);
+ return _NUMBER_;
+ }
YY_BREAK
case 56:
YY_RULE_SETUP
-#line 257 "lex.l"
-{ /* saw closing quote - all done */
+#line 271 "lex.l"
+{ /* saw closing quote - all done */
+
+ SIZED_STRING* s;
+
+ if (yyextra->lex_buf_len == 0)
+ {
+ yyerror(yyscanner, "empty string");
+ }
+
+ *yyextra->lex_buf_ptr = '\0';
+
+ BEGIN(INITIAL);
+
+ s = (SIZED_STRING*) yr_malloc(yyextra->lex_buf_len + sizeof(SIZED_STRING));
- SIZED_STRING* s;
+ s->length = yyextra->lex_buf_len;
- if (yyextra->lex_buf_len == 0)
- {
- yyerror(yyscanner, "empty string");
- }
+ strcpy(s->c_string, yyextra->lex_buf);
- *yyextra->lex_buf_ptr = '\0';
+ yylval->sized_string = s;
- BEGIN(INITIAL);
-
- s = (SIZED_STRING*) yr_malloc(yyextra->lex_buf_len + sizeof(SIZED_STRING));
-
- s->length = yyextra->lex_buf_len;
-
- strcpy(s->c_string, yyextra->lex_buf);
-
- yylval->sized_string = s;
-
- return _TEXTSTRING_;
- }
+ return _TEXTSTRING_;
+ }
YY_BREAK
case 57:
YY_RULE_SETUP
-#line 281 "lex.l"
-{ *yyextra->lex_buf_ptr++ = '\t'; yyextra->lex_buf_len++; }
+#line 295 "lex.l"
+{ LEX_CHECK_SPACE_OK("\t", yyextra->lex_buf_len, LEX_BUF_SIZE); *yyextra->lex_buf_ptr++ = '\t'; yyextra->lex_buf_len++;}
YY_BREAK
case 58:
YY_RULE_SETUP
-#line 282 "lex.l"
-{ *yyextra->lex_buf_ptr++ = '\"'; yyextra->lex_buf_len++; }
+#line 296 "lex.l"
+{ LEX_CHECK_SPACE_OK("\"", yyextra->lex_buf_len, LEX_BUF_SIZE); *yyextra->lex_buf_ptr++ = '\"'; yyextra->lex_buf_len++;}
YY_BREAK
case 59:
YY_RULE_SETUP
-#line 283 "lex.l"
-{ *yyextra->lex_buf_ptr++ = '\\'; yyextra->lex_buf_len++; }
+#line 297 "lex.l"
+{ LEX_CHECK_SPACE_OK("\\", yyextra->lex_buf_len, LEX_BUF_SIZE); *yyextra->lex_buf_ptr++ = '\\'; yyextra->lex_buf_len++;}
YY_BREAK
case 60:
YY_RULE_SETUP
-#line 285 "lex.l"
+#line 299 "lex.l"
{
- int result;
+ int result;
- sscanf( yytext + 2, "%x", &result );
-
- *yyextra->lex_buf_ptr++ = result;
- yyextra->lex_buf_len++;
- }
+ sscanf( yytext + 2, "%x", &result );
+ LEX_CHECK_SPACE_OK("X", yyextra->lex_buf_len, LEX_BUF_SIZE);
+ *yyextra->lex_buf_ptr++ = result;
+ yyextra->lex_buf_len++;
+ }
YY_BREAK
case 61:
YY_RULE_SETUP
-#line 294 "lex.l"
+#line 308 "lex.l"
{
- YYTEXT_TO_BUFFER;
- }
+ YYTEXT_TO_BUFFER;
+ }
YY_BREAK
case 62:
/* rule 62 can match eol */
YY_RULE_SETUP
-#line 298 "lex.l"
+#line 312 "lex.l"
{
- yyerror(yyscanner, "unterminated string");
- yyterminate();
- }
+ yyerror(yyscanner, "unterminated string");
+ yyterminate();
+ }
YY_BREAK
case 63:
/* rule 63 can match eol */
YY_RULE_SETUP
-#line 303 "lex.l"
+#line 317 "lex.l"
{
- yyerror(yyscanner, "illegal escape sequence");
- }
+ yyerror(yyscanner, "illegal escape sequence");
+ }
YY_BREAK
case 64:
YY_RULE_SETUP
-#line 308 "lex.l"
-{
- SIZED_STRING* s;
+#line 322 "lex.l"
+{
+ SIZED_STRING* s;
- if (yyextra->lex_buf_len == 0)
- {
- yyerror(yyscanner, "empty regular expression");
- }
+ if (yyextra->lex_buf_len == 0)
+ {
+ yyerror(yyscanner, "empty regular expression");
+ }
- *yyextra->lex_buf_ptr = '\0';
+ *yyextra->lex_buf_ptr = '\0';
- BEGIN(INITIAL);
+ BEGIN(INITIAL);
- s = (SIZED_STRING*) yr_malloc(yyextra->lex_buf_len + sizeof(SIZED_STRING));
+ s = (SIZED_STRING*) yr_malloc(yyextra->lex_buf_len + sizeof(SIZED_STRING));
- s->length = yyextra->lex_buf_len;
- strcpy(s->c_string, yyextra->lex_buf);
-
- yylval->sized_string = s;
+ s->length = yyextra->lex_buf_len;
+ strcpy(s->c_string, yyextra->lex_buf);
- return _REGEXP_;
- }
+ yylval->sized_string = s;
+
+ return _REGEXP_;
+ }
YY_BREAK
case 65:
YY_RULE_SETUP
-#line 330 "lex.l"
-{
- *yyextra->lex_buf_ptr++ = '/';
- yyextra->lex_buf_len++ ;
- }
+#line 344 "lex.l"
+{
+ LEX_CHECK_SPACE_OK("/", yyextra->lex_buf_len, LEX_BUF_SIZE);
+ *yyextra->lex_buf_ptr++ = '/';
+ yyextra->lex_buf_len++ ;
+ }
YY_BREAK
case 66:
YY_RULE_SETUP
-#line 335 "lex.l"
-{
- *yyextra->lex_buf_ptr++ = yytext[0];
- *yyextra->lex_buf_ptr++ = yytext[1];
- yyextra->lex_buf_len += 2;
- }
+#line 350 "lex.l"
+{
+ LEX_CHECK_SPACE_OK("\\.", yyextra->lex_buf_len, LEX_BUF_SIZE);
+ *yyextra->lex_buf_ptr++ = yytext[0];
+ *yyextra->lex_buf_ptr++ = yytext[1];
+ yyextra->lex_buf_len += 2;
+ }
YY_BREAK
case 67:
YY_RULE_SETUP
-#line 341 "lex.l"
+#line 357 "lex.l"
{
- YYTEXT_TO_BUFFER;
- }
+ YYTEXT_TO_BUFFER;
+ }
YY_BREAK
case 68:
/* rule 68 can match eol */
YY_RULE_SETUP
-#line 345 "lex.l"
+#line 361 "lex.l"
{
- yyerror(yyscanner, "unterminated regular expression");
- yyterminate();
- }
+ yyerror(yyscanner, "unterminated regular expression");
+ yyterminate();
+ }
YY_BREAK
case 69:
YY_RULE_SETUP
-#line 350 "lex.l"
+#line 366 "lex.l"
{
- yyextra->lex_buf_ptr = yyextra->lex_buf;
- yyextra->lex_buf_len = 0;
- BEGIN(str);
- }
+ yyextra->lex_buf_ptr = yyextra->lex_buf;
+ yyextra->lex_buf_len = 0;
+ BEGIN(str);
+ }
YY_BREAK
case 70:
YY_RULE_SETUP
-#line 356 "lex.l"
+#line 372 "lex.l"
{
- yyextra->lex_buf_ptr = yyextra->lex_buf;
- yyextra->lex_buf_len = 0;
- BEGIN(regexp);
- }
+ yyextra->lex_buf_ptr = yyextra->lex_buf;
+ yyextra->lex_buf_len = 0;
+ BEGIN(regexp);
+ }
YY_BREAK
case 71:
YY_RULE_SETUP
-#line 362 "lex.l"
-{
- int len = strlen(yytext);
-
- SIZED_STRING* s = (SIZED_STRING*) yr_malloc(len + sizeof(SIZED_STRING));
+#line 378 "lex.l"
+{
+ int len = strlen(yytext);
+
+ SIZED_STRING* s = (SIZED_STRING*) yr_malloc(len + sizeof(SIZED_STRING));
- s->length = len;
+ s->length = len;
- strcpy(s->c_string, yytext);
+ strcpy(s->c_string, yytext);
- yylval->sized_string = s;
-
- return _HEXSTRING_;
- }
+ yylval->sized_string = s;
+
+ return _HEXSTRING_;
+ }
YY_BREAK
case 72:
/* rule 72 can match eol */
YY_RULE_SETUP
-#line 376 "lex.l"
+#line 392 "lex.l"
/* skip whitespace */
YY_BREAK
case 73:
YY_RULE_SETUP
-#line 378 "lex.l"
-{
- return yytext[0];
- }
+#line 394 "lex.l"
+{
+ return yytext[0];
+ }
YY_BREAK
case 74:
YY_RULE_SETUP
-#line 381 "lex.l"
+#line 397 "lex.l"
ECHO;
YY_BREAK
-#line 1594 "lex.c"
+#line 1626 "lex.c"
case YY_END_OF_BUFFER:
{
@@ -1775,7 +1807,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{
- yy_size_t num_to_read =
+ int num_to_read =
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 )
@@ -1789,7 +1821,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( b->yy_is_our_buffer )
{
- yy_size_t new_size = b->yy_buf_size * 2;
+ int new_size = b->yy_buf_size * 2;
if ( new_size <= 0 )
b->yy_buf_size += b->yy_buf_size / 8;
@@ -1820,7 +1852,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Read in more data. */
YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
- yyg->yy_n_chars, num_to_read );
+ yyg->yy_n_chars, (size_t) num_to_read );
YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
}
@@ -1933,7 +1965,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
{ /* need to shift things up to make room */
/* +2 for EOB chars. */
- register yy_size_t number_to_move = yyg->yy_n_chars + 2;
+ register int number_to_move = yyg->yy_n_chars + 2;
register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
register char *source =
@@ -1987,7 +2019,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{ /* need more input */
- yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
++yyg->yy_c_buf_p;
switch ( yy_get_next_buffer( yyscanner ) )
@@ -2011,7 +2043,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
case EOB_ACT_END_OF_FILE:
{
if ( yywrap(yyscanner ) )
- return 0;
+ return EOF;
if ( ! yyg->yy_did_buffer_switch_on_eof )
YY_NEW_FILE;
@@ -2278,7 +2310,7 @@ void yypop_buffer_state (yyscan_t yyscanner)
*/
static void yyensure_buffer_stack (yyscan_t yyscanner)
{
- yy_size_t num_to_alloc;
+ int num_to_alloc;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!yyg->yy_buffer_stack) {
@@ -2371,16 +2403,17 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
* scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
char *buf;
- yy_size_t n, i;
+ yy_size_t n;
+ int i;
/* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2;
@@ -2490,7 +2523,7 @@ FILE *yyget_out (yyscan_t yyscanner)
/** Get the length of the current token.
* @param yyscanner The scanner object.
*/
-yy_size_t yyget_leng (yyscan_t yyscanner)
+int yyget_leng (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyleng;
@@ -2765,107 +2798,106 @@ void yyfree (void * ptr , yyscan_t yyscanner)
#define YYTABLES_NAME "yytables"
-#line 381 "lex.l"
+#line 397 "lex.l"
+
+
+void yyerror(yyscan_t yyscanner, const char *error_message)
+{
+ YARA_CONTEXT* context = yyget_extra(yyscanner);
+ char message[512] = {'\0'};
+ char* file_name = NULL;
+ /*
+ if error_message != NULL the error comes from yyparse internal code
+ else the error comes from my code and the error code is set in context->last_result
+ */
+ context->errors++;
+ context->last_error_line = yyget_lineno(yyscanner);
-void yyerror(yyscan_t yyscanner, const char *error_message)
-{
- YARA_CONTEXT* context = yyget_extra(yyscanner);
-
- char message[512];
- char* file_name;
-
- /*
- if error_message != NULL the error comes from yyparse internal code
- else the error comes from my code and the error code is set in context->last_result
- */
-
- context->errors++;
- context->last_error_line = yyget_lineno(yyscanner);
-
- if (context->file_name_stack_ptr > 0)
- {
- file_name = context->file_name_stack[context->file_name_stack_ptr - 1];
- }
- else
- {
- file_name = NULL;
- }
-
- if (error_message != NULL)
- {
- context->last_error = ERROR_SYNTAX_ERROR;
- strncpy(context->last_error_extra_info, error_message, sizeof(message));
-
- if (context->error_report_function != NULL)
- {
- context->error_report_function( file_name,
- context->last_error_line,
- error_message);
- }
- }
- else
- {
- context->last_error = context->last_result;
-
- if (context->error_report_function != NULL)
- {
- yr_get_error_message(context, message, sizeof(message));
-
- context->error_report_function( file_name,
- context->last_error_line,
- message);
- }
- }
-
- context->last_result = ERROR_SUCCESS;
+ if (context->file_name_stack_ptr > 0)
+ {
+ file_name = context->file_name_stack[context->file_name_stack_ptr - 1];
+ }
+ else
+ {
+ file_name = NULL;
+ }
+
+ if (error_message != NULL)
+ {
+ context->last_error = ERROR_SYNTAX_ERROR;
+ strncpy(context->last_error_extra_info, error_message, sizeof(message) - 1);
+ context->last_error_extra_info[sizeof(message)-1] = '\0';
+
+ if (context->error_report_function != NULL)
+ {
+ context->error_report_function(file_name,
+ context->last_error_line,
+ error_message);
+ }
+ }
+ else
+ {
+ context->last_error = context->last_result;
+
+ if (context->error_report_function != NULL)
+ {
+ yr_get_error_message(context, message, sizeof(message));
+
+ context->error_report_function(file_name,
+ context->last_error_line,
+ message);
+ }
+ }
+
+ context->last_result = ERROR_SUCCESS;
}
int parse_rules_string(const char* rules_string, YARA_CONTEXT* context)
{
- yyscan_t yyscanner;
- YY_BUFFER_STATE state;
-
+ yyscan_t yyscanner;
+ YY_BUFFER_STATE state;
+
yylex_init(&yyscanner);
- yyset_extra(context,yyscanner);
+ yyset_extra(context,yyscanner);
- state = yy_scan_string(rules_string,yyscanner);
-
- yyset_lineno(1,yyscanner);
+ state = yy_scan_string(rules_string,yyscanner);
+
+ yyset_lineno(1,yyscanner);
yyparse(yyscanner);
- yylex_destroy(yyscanner);
-
- return context->errors;
+ yylex_destroy(yyscanner);
+
+ return context->errors;
}
int parse_rules_file(FILE* rules_file, YARA_CONTEXT* context)
-{
- yyscan_t yyscanner;
-
+{
+ yyscan_t yyscanner;
+
yylex_init(&yyscanner);
- #ifdef DEBUG
- yyset_debug(1,yyscanner);
- #endif
-
- yyset_in(rules_file,yyscanner);
- yyset_extra(context,yyscanner);
-
+#ifdef DEBUG
+ yyset_debug(1,yyscanner);
+#endif
+
+ yyset_in(rules_file,yyscanner);
+ yyset_extra(context,yyscanner);
+
yyparse(yyscanner);
yylex_destroy(yyscanner);
- return context->errors;
+ return context->errors;
}
diff --git a/libyara/lex.l b/libyara/lex.l
index 122bf63..7024ded 100644
--- a/libyara/lex.l
+++ b/libyara/lex.l
@@ -12,19 +12,28 @@
#include "lex.h"
#include "yara.h"
-#define YYTEXT_TO_BUFFER { \
- char *yptr = yytext; \
- while ( *yptr ) \
- { \
- *yyextra->lex_buf_ptr++ = *yptr++; \
- yyextra->lex_buf_len++; \
- } \
- }
-
+#define LEX_CHECK_SPACE_OK(data, current_size, max_length) \
+ if (strlen(data) + current_size >= max_length - 1) \
+ { \
+ yyerror(yyscanner, "out of space in lex_buf"); \
+ yyterminate(); \
+ }
+
+#define YYTEXT_TO_BUFFER \
+ { \
+ char *yptr = yytext; \
+ LEX_CHECK_SPACE_OK(yptr, yyextra->lex_buf_len, LEX_BUF_SIZE); \
+ while ( *yptr ) \
+ { \
+ *yyextra->lex_buf_ptr++ = *yptr++; \
+ yyextra->lex_buf_len++; \
+ } \
+ }
+
#ifdef WIN32
#define snprintf _snprintf
#endif
-
+
%}
%option reentrant bison-bridge
@@ -39,444 +48,450 @@
%x regexp
%x include
-
digit [0-9]
letter [a-zA-Z]
hexdigit [a-fA-F0-9]
%%
-"<" { return _LT_; }
-">" { return _GT_; }
-"<=" { return _LE_; }
-">=" { return _GE_; }
-"==" { return _EQ_; }
-"!=" { return _NEQ_; }
-"private" { return _PRIVATE_; }
-"global" { return _GLOBAL_; }
-"rule" { return _RULE_; }
-"meta" { return _META_; }
-"strings" { return _STRINGS_; }
-"ascii" { return _ASCII_; }
-"wide" { return _WIDE_; }
-"fullword" { return _FULLWORD_; }
-"nocase" { return _NOCASE_; }
-"condition" { return _CONDITION_; }
-"true" { return _TRUE_; }
-"false" { return _FALSE_; }
-"not" { return _NOT_; }
-"and" { return _AND_; }
-"or" { return _OR_; }
-"at" { return _AT_; }
-"in" { return _IN_; }
-"of" { return _OF_; }
-"them" { return _THEM_; }
-"for" { return _FOR_; }
-"all" { return _ALL_; }
-"any" { return _ANY_; }
-"entrypoint" { return _ENTRYPOINT_; }
-"filesize" { return _SIZE_; }
-"rva" { return _RVA_; }
-"offset" { return _OFFSET_; }
-"file" { return _FILE_; }
-"section" { return _SECTION_; }
-"uint8" { return _UINT8_; }
-"uint16" { return _UINT16_; }
-"uint32" { return _UINT32_; }
-"int8" { return _INT8_; }
-"int16" { return _INT16_; }
-"int32" { return _INT32_; }
-"matches" { return _MATCHES_; }
-"contains" { return _CONTAINS_; }
-"index" { return _INDEX_; }
-
-
-
-"/*"([^\*]|\*[^\/])*"*/" { /* skip comments */ }
-
-"//"[^\n]* { /* skip single-line comments */ }
-
-include[ \t]+\" {
- yyextra->lex_buf_ptr = yyextra->lex_buf;
- yyextra->lex_buf_len = 0;
- BEGIN(include);
- }
-
-<include>[^\"]+ {
- YYTEXT_TO_BUFFER;
- }
-
-<include>\" {
- char buffer[1024];
- char *current_file_name;
- char *s = NULL;
- char *b = NULL;
- char *f;
- FILE* fh;
- YARA_CONTEXT* context = yyget_extra(yyscanner);
-
- if (context->allow_includes)
- {
- *yyextra->lex_buf_ptr = '\0'; // null-terminate included file path
-
- // move path of current source file into buffer
-
- current_file_name = yr_get_current_file_name(context);
-
- if (current_file_name != NULL)
- {
- strncpy(buffer, yr_get_current_file_name(context), sizeof(buffer));
- }
- else
- {
- buffer[0] = '\0';
- }
-
- // make included file path relative to current source file
-
- s = strrchr(buffer, '/');
-
- #ifdef WIN32
- b = strrchr(buffer, '\\'); // in Windows both path delimiters are accepted
- #endif
-
- if (s != NULL || b != NULL)
- {
- f = (b > s)? (b + 1): (s + 1);
-
- strncpy(f, yyextra->lex_buf, sizeof(buffer) - (f - buffer));
-
- fh = fopen(buffer, "r");
-
- // if include file was not found relative to current source file, try to open it
- // with path as specified by user (maybe user wrote a full path)
-
- if (fh == NULL)
- {
- fh = fopen(yyextra->lex_buf, "r");
- }
- }
- else
- {
- fh = fopen(yyextra->lex_buf, "r");
- }
-
- if (fh != NULL)
- {
- if (yr_push_file_name(context, yyextra->lex_buf) == ERROR_INCLUDES_CIRCULAR_REFERENCE)
- {
- yyerror(yyscanner, "includes circular reference");
- yyterminate();
- }
-
- yypush_buffer_state(yy_create_buffer(fh, YY_BUF_SIZE, yyscanner), yyscanner);
- }
- else
- {
- snprintf(buffer, sizeof(buffer), "can't open include file: %s", yyextra->lex_buf);
- yyerror(yyscanner, buffer);
- }
-
- }
- else // not allowing includes
- {
- yyerror(yyscanner, "includes are disabled");
- yyterminate();
- }
-
- BEGIN(INITIAL);
- }
-
-<<EOF>> {
- YARA_CONTEXT* context = yyget_extra(yyscanner);
-
- yr_pop_file_name(context);
-
- yypop_buffer_state(yyscanner);
-
- if ( !YY_CURRENT_BUFFER )
- {
- yyterminate();
- }
- }
-
-
-$({letter}|{digit}|_)*"*" {
- yylval->c_string = (char*) yr_strdup(yytext);
- return _STRING_IDENTIFIER_WITH_WILDCARD_;
- }
-
-$({letter}|{digit}|_)* {
- yylval->c_string = (char*) yr_strdup(yytext);
- return _STRING_IDENTIFIER_;
- }
-
-
-#({letter}|{digit}|_)* {
- yylval->c_string = (char*) yr_strdup(yytext);
- yylval->c_string[0] = '$'; /* replace # by $*/
- return _STRING_COUNT_;
- }
-
-@({letter}|{digit}|_)* {
- yylval->c_string = (char*) yr_strdup(yytext);
- yylval->c_string[0] = '$'; /* replace @ by $*/
- return _STRING_OFFSET_;
- }
-
-({letter}|_)({letter}|{digit}|_)* {
- if (strlen(yytext) > 128)
- {
- yyerror(yyscanner, "indentifier too long");
- }
-
- yylval->c_string = (char*) yr_strdup(yytext);
- return _IDENTIFIER_;
- }
-
-{digit}+(MB|KB){0,1} {
- yylval->integer = (size_t) atol(yytext);
-
- if (strstr(yytext, "KB") != NULL)
- {
- yylval->integer *= 1024;
- }
- else if (strstr(yytext, "MB") != NULL)
- {
- yylval->integer *= 1048576;
- }
-
- return _NUMBER_;
- }
-
-0x{hexdigit}+ {
- yylval->integer = xtoi(yytext + 2);
- return _NUMBER_;
- }
-
-<str>\" { /* saw closing quote - all done */
-
- SIZED_STRING* s;
-
- if (yyextra->lex_buf_len == 0)
- {
- yyerror(yyscanner, "empty string");
- }
-
- *yyextra->lex_buf_ptr = '\0';
-
- BEGIN(INITIAL);
-
- s = (SIZED_STRING*) yr_malloc(yyextra->lex_buf_len + sizeof(SIZED_STRING));
-
- s->length = yyextra->lex_buf_len;
-
- strcpy(s->c_string, yyextra->lex_buf);
-
- yylval->sized_string = s;
-
- return _TEXTSTRING_;
- }
-
-<str>\\t { *yyextra->lex_buf_ptr++ = '\t'; yyextra->lex_buf_len++; }
-<str>\\\" { *yyextra->lex_buf_ptr++ = '\"'; yyextra->lex_buf_len++; }
-<str>\\\\ { *yyextra->lex_buf_ptr++ = '\\'; yyextra->lex_buf_len++; }
-
-<str>\\x{hexdigit}{2} {
- int result;
-
- sscanf( yytext + 2, "%x", &result );
-
- *yyextra->lex_buf_ptr++ = result;
- yyextra->lex_buf_len++;
- }
-
-<str>[^\\\n\"]+ {
- YYTEXT_TO_BUFFER;
- }
-
-<str>\n {
- yyerror(yyscanner, "unterminated string");
- yyterminate();
- }
-
-<str>\\(.|\n) {
- yyerror(yyscanner, "illegal escape sequence");
- }
-
-
-<regexp>"/" {
- SIZED_STRING* s;
-
- if (yyextra->lex_buf_len == 0)
- {
- yyerror(yyscanner, "empty regular expression");
- }
-
- *yyextra->lex_buf_ptr = '\0';
-
- BEGIN(INITIAL);
-
- s = (SIZED_STRING*) yr_malloc(yyextra->lex_buf_len + sizeof(SIZED_STRING));
-
- s->length = yyextra->lex_buf_len;
- strcpy(s->c_string, yyextra->lex_buf);
-
- yylval->sized_string = s;
-
- return _REGEXP_;
- }
-
-<regexp>\\\/ {
- *yyextra->lex_buf_ptr++ = '/';
- yyextra->lex_buf_len++ ;
- }
-
-<regexp>\\. {
- *yyextra->lex_buf_ptr++ = yytext[0];
- *yyextra->lex_buf_ptr++ = yytext[1];
- yyextra->lex_buf_len += 2;
- }
-
-<regexp>[^/\n\\]+ {
- YYTEXT_TO_BUFFER;
- }
-
-<regexp>\n {
- yyerror(yyscanner, "unterminated regular expression");
- yyterminate();
- }
-
-\" {
- yyextra->lex_buf_ptr = yyextra->lex_buf;
- yyextra->lex_buf_len = 0;
- BEGIN(str);
- }
-
-"/" {
- yyextra->lex_buf_ptr = yyextra->lex_buf;
- yyextra->lex_buf_len = 0;
- BEGIN(regexp);
- }
-
-\{({hexdigit}|[ \-|\?\[\]\(\)])+\} {
- int len = strlen(yytext);
-
- SIZED_STRING* s = (SIZED_STRING*) yr_malloc(len + sizeof(SIZED_STRING));
-
- s->length = len;
-
- strcpy(s->c_string, yytext);
-
- yylval->sized_string = s;
-
- return _HEXSTRING_;
- }
-
-[ \t\r\n] /* skip whitespace */
-
-. {
- return yytext[0];
- }
-%%
+"<" { return _LT_; }
+">" { return _GT_; }
+"<=" { return _LE_; }
+">=" { return _GE_; }
+"==" { return _EQ_; }
+"!=" { return _NEQ_; }
+"private" { return _PRIVATE_; }
+"global" { return _GLOBAL_; }
+"rule" { return _RULE_; }
+"meta" { return _META_; }
+"strings" { return _STRINGS_; }
+"ascii" { return _ASCII_; }
+"wide" { return _WIDE_; }
+"fullword" { return _FULLWORD_; }
+"nocase" { return _NOCASE_; }
+"condition" { return _CONDITION_; }
+"true" { return _TRUE_; }
+"false" { return _FALSE_; }
+"not" { return _NOT_; }
+"and" { return _AND_; }
+"or" { return _OR_; }
+"at" { return _AT_; }
+"in" { return _IN_; }
+"of" { return _OF_; }
+"them" { return _THEM_; }
+"for" { return _FOR_; }
+"all" { return _ALL_; }
+"any" { return _ANY_; }
+"entrypoint" { return _ENTRYPOINT_; }
+"filesize" { return _SIZE_; }
+"rva" { return _RVA_; }
+"offset" { return _OFFSET_; }
+"file" { return _FILE_; }
+"section" { return _SECTION_; }
+"uint8" { return _UINT8_; }
+"uint16" { return _UINT16_; }
+"uint32" { return _UINT32_; }
+"int8" { return _INT8_; }
+"int16" { return _INT16_; }
+"int32" { return _INT32_; }
+"matches" { return _MATCHES_; }
+"contains" { return _CONTAINS_; }
+"index" { return _INDEX_; }
+
+
+"/*"([^\*]|\*[^\/])*"*/" { /* skip comments */ }
+
+"//"[^\n]* { /* skip single-line comments */ }
+
+include[ \t]+\" {
+ yyextra->lex_buf_ptr = yyextra->lex_buf;
+ yyextra->lex_buf_len = 0;
+ BEGIN(include);
+ }
+
+<include>[^\"]+ {
+ YYTEXT_TO_BUFFER;
+ }
+
+<include>\" {
+ char buffer[1024];
+ char *current_file_name;
+ char *s = NULL;
+ char *b = NULL;
+ char *f;
+ FILE* fh;
+ YARA_CONTEXT* context = yyget_extra(yyscanner);
+
+ if (context->allow_includes)
+ {
+ *yyextra->lex_buf_ptr = '\0'; // null-terminate included file path
+
+ // move path of current source file into buffer
+ current_file_name = yr_get_current_file_name(context);
+
+ if (current_file_name != NULL)
+ {
+ strncpy(buffer, yr_get_current_file_name(context), sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ }
+ else
+ {
+ buffer[0] = '\0';
+ }
+
+ // make included file path relative to current source file
+ s = strrchr(buffer, '/');
+
+ #ifdef WIN32
+ b = strrchr(buffer, '\\'); // in Windows both path delimiters are accepted
+ #endif
+
+ if (s != NULL || b != NULL)
+ {
+ f = (b > s)? (b + 1): (s + 1);
+
+ strncpy(f, yyextra->lex_buf, sizeof(buffer) - (f - buffer));
+ buffer[sizeof(buffer)-1] = '\0';
+
+ // SECURITY: Potential for directory traversal here.
+ fh = fopen(buffer, "r");
+
+ // if include file was not found relative to current source file, try to open it
+ // with path as specified by user (maybe user wrote a full path)
+ if (fh == NULL)
+ {
+ // SECURITY: Potential for directory traversal here.
+ fh = fopen(yyextra->lex_buf, "r");
+ }
+ }
+ else
+ {
+ // SECURITY: Potential for directory traversal here.
+ fh = fopen(yyextra->lex_buf, "r");
+ }
+
+ if (fh != NULL)
+ {
+ int error_code = ERROR_SUCCESS;
+ if ((error_code = yr_push_file_name(context, yyextra->lex_buf)) != ERROR_SUCCESS)
+ {
+ if (error_code == ERROR_INCLUDES_CIRCULAR_REFERENCE)
+ {
+ yyerror(yyscanner, "includes circular reference");
+ }
+ else if (error_code == ERROR_INCLUDE_DEPTH_EXCEEDED)
+ {
+ yyerror(yyscanner, "includes circular reference");
+ }
+ yyterminate();
+ }
+ yypush_buffer_state(yy_create_buffer(fh, YY_BUF_SIZE, yyscanner), yyscanner);
+ }
+ else
+ {
+ snprintf(buffer, sizeof(buffer), "can't open include file: %s", yyextra->lex_buf);
+ yyerror(yyscanner, buffer);
+ }
+ }
+ else // not allowing includes
+ {
+ yyerror(yyscanner, "includes are disabled");
+ yyterminate();
+ }
+
+ BEGIN(INITIAL);
+ }
+
+<<EOF>> {
+ YARA_CONTEXT* context = yyget_extra(yyscanner);
+
+ yr_pop_file_name(context);
+
+ yypop_buffer_state(yyscanner);
+
+ if (!YY_CURRENT_BUFFER)
+ {
+ yyterminate();
+ }
+ }
+
+
+$({letter}|{digit}|_)*"*" {
+ yylval->c_string = (char*) yr_strdup(yytext);
+ return _STRING_IDENTIFIER_WITH_WILDCARD_;
+ }
+
+$({letter}|{digit}|_)* {
+ yylval->c_string = (char*) yr_strdup(yytext);
+ return _STRING_IDENTIFIER_;
+ }
+
+
+#({letter}|{digit}|_)* {
+ yylval->c_string = (char*) yr_strdup(yytext);
+ yylval->c_string[0] = '$'; /* replace # by $*/
+ return _STRING_COUNT_;
+ }
+
+@({letter}|{digit}|_)* {
+ yylval->c_string = (char*) yr_strdup(yytext);
+ yylval->c_string[0] = '$'; /* replace @ by $*/
+ return _STRING_OFFSET_;
+ }
+
+({letter}|_)({letter}|{digit}|_)* {
+ if (strlen(yytext) > 128)
+ {
+ yyerror(yyscanner, "indentifier too long");
+ }
+
+ yylval->c_string = (char*) yr_strdup(yytext);
+ return _IDENTIFIER_;
+ }
+
+{digit}+(MB|KB){0,1} {
+ yylval->integer = (size_t) atol(yytext);
+
+ if (strstr(yytext, "KB") != NULL)
+ {
+ yylval->integer *= 1024;
+ }
+ else if (strstr(yytext, "MB") != NULL)
+ {
+ yylval->integer *= 1048576;
+ }
+ return _NUMBER_;
+ }
+
+0x{hexdigit}+ {
+ yylval->integer = xtoi(yytext + 2);
+ return _NUMBER_;
+ }
+
+<str>\" { /* saw closing quote - all done */
+
+ SIZED_STRING* s;
+
+ if (yyextra->lex_buf_len == 0)
+ {
+ yyerror(yyscanner, "empty string");
+ }
+
+ *yyextra->lex_buf_ptr = '\0';
+
+ BEGIN(INITIAL);
+
+ s = (SIZED_STRING*) yr_malloc(yyextra->lex_buf_len + sizeof(SIZED_STRING));
+
+ s->length = yyextra->lex_buf_len;
+
+ strcpy(s->c_string, yyextra->lex_buf);
+
+ yylval->sized_string = s;
+
+ return _TEXTSTRING_;
+ }
+
+<str>\\t { LEX_CHECK_SPACE_OK("\t", yyextra->lex_buf_len, LEX_BUF_SIZE); *yyextra->lex_buf_ptr++ = '\t'; yyextra->lex_buf_len++;}
+<str>\\\" { LEX_CHECK_SPACE_OK("\"", yyextra->lex_buf_len, LEX_BUF_SIZE); *yyextra->lex_buf_ptr++ = '\"'; yyextra->lex_buf_len++;}
+<str>\\\\ { LEX_CHECK_SPACE_OK("\\", yyextra->lex_buf_len, LEX_BUF_SIZE); *yyextra->lex_buf_ptr++ = '\\'; yyextra->lex_buf_len++;}
+
+<str>\\x{hexdigit}{2} {
+ int result;
+
+ sscanf( yytext + 2, "%x", &result );
+ LEX_CHECK_SPACE_OK("X", yyextra->lex_buf_len, LEX_BUF_SIZE);
+ *yyextra->lex_buf_ptr++ = result;
+ yyextra->lex_buf_len++;
+ }
+
+<str>[^\\\n\"]+ {
+ YYTEXT_TO_BUFFER;
+ }
+
+<str>\n {
+ yyerror(yyscanner, "unterminated string");
+ yyterminate();
+ }
+
+<str>\\(.|\n) {
+ yyerror(yyscanner, "illegal escape sequence");
+ }
+
+
+<regexp>"/" {
+ SIZED_STRING* s;
+
+ if (yyextra->lex_buf_len == 0)
+ {
+ yyerror(yyscanner, "empty regular expression");
+ }
+
+ *yyextra->lex_buf_ptr = '\0';
+
+ BEGIN(INITIAL);
+
+ s = (SIZED_STRING*) yr_malloc(yyextra->lex_buf_len + sizeof(SIZED_STRING));
+
+ s->length = yyextra->lex_buf_len;
+ strcpy(s->c_string, yyextra->lex_buf);
+
+ yylval->sized_string = s;
+
+ return _REGEXP_;
+ }
+<regexp>\\\/ {
+ LEX_CHECK_SPACE_OK("/", yyextra->lex_buf_len, LEX_BUF_SIZE);
+ *yyextra->lex_buf_ptr++ = '/';
+ yyextra->lex_buf_len++ ;
+ }
+<regexp>\\. {
+ LEX_CHECK_SPACE_OK("\\.", yyextra->lex_buf_len, LEX_BUF_SIZE);
+ *yyextra->lex_buf_ptr++ = yytext[0];
+ *yyextra->lex_buf_ptr++ = yytext[1];
+ yyextra->lex_buf_len += 2;
+ }
+
+<regexp>[^/\n\\]+ {
+ YYTEXT_TO_BUFFER;
+ }
+
+<regexp>\n {
+ yyerror(yyscanner, "unterminated regular expression");
+ yyterminate();
+ }
+
+\" {
+ yyextra->lex_buf_ptr = yyextra->lex_buf;
+ yyextra->lex_buf_len = 0;
+ BEGIN(str);
+ }
+
+"/" {
+ yyextra->lex_buf_ptr = yyextra->lex_buf;
+ yyextra->lex_buf_len = 0;
+ BEGIN(regexp);
+ }
+
+\{({hexdigit}|[ \-|\?\[\]\(\)])+\} {
+ int len = strlen(yytext);
+
+ SIZED_STRING* s = (SIZED_STRING*) yr_malloc(len + sizeof(SIZED_STRING));
+
+ s->length = len;
+
+ strcpy(s->c_string, yytext);
+
+ yylval->sized_string = s;
+
+ return _HEXSTRING_;
+ }
+
+[ \t\r\n] /* skip whitespace */
+
+. {
+ return yytext[0];
+ }
+%%
void yyerror(yyscan_t yyscanner, const char *error_message)
-{
- YARA_CONTEXT* context = yyget_extra(yyscanner);
-
- char message[512];
- char* file_name;
-
- /*
- if error_message != NULL the error comes from yyparse internal code
- else the error comes from my code and the error code is set in context->last_result
- */
-
- context->errors++;
- context->last_error_line = yyget_lineno(yyscanner);
-
- if (context->file_name_stack_ptr > 0)
- {
- file_name = context->file_name_stack[context->file_name_stack_ptr - 1];
- }
- else
- {
- file_name = NULL;
- }
-
- if (error_message != NULL)
- {
- context->last_error = ERROR_SYNTAX_ERROR;
- strncpy(context->last_error_extra_info, error_message, sizeof(message));
-
- if (context->error_report_function != NULL)
- {
- context->error_report_function( file_name,
- context->last_error_line,
- error_message);
- }
- }
- else
- {
- context->last_error = context->last_result;
-
- if (context->error_report_function != NULL)
- {
- yr_get_error_message(context, message, sizeof(message));
-
- context->error_report_function( file_name,
- context->last_error_line,
- message);
- }
- }
-
- context->last_result = ERROR_SUCCESS;
+{
+ YARA_CONTEXT* context = yyget_extra(yyscanner);
+
+ char message[512] = {'\0'};
+ char* file_name = NULL;
+
+ /*
+ if error_message != NULL the error comes from yyparse internal code
+ else the error comes from my code and the error code is set in context->last_result
+ */
+
+ context->errors++;
+ context->last_error_line = yyget_lineno(yyscanner);
+
+ if (context->file_name_stack_ptr > 0)
+ {
+ file_name = context->file_name_stack[context->file_name_stack_ptr - 1];
+ }
+ else
+ {
+ file_name = NULL;
+ }
+
+ if (error_message != NULL)
+ {
+ context->last_error = ERROR_SYNTAX_ERROR;
+ strncpy(context->last_error_extra_info, error_message, sizeof(message) - 1);
+ context->last_error_extra_info[sizeof(message)-1] = '\0';
+
+ if (context->error_report_function != NULL)
+ {
+ context->error_report_function(file_name,
+ context->last_error_line,
+ error_message);
+ }
+ }
+ else
+ {
+ context->last_error = context->last_result;
+
+ if (context->error_report_function != NULL)
+ {
+ yr_get_error_message(context, message, sizeof(message));
+
+ context->error_report_function(file_name,
+ context->last_error_line,
+ message);
+ }
+ }
+
+ context->last_result = ERROR_SUCCESS;
}
int parse_rules_string(const char* rules_string, YARA_CONTEXT* context)
{
- yyscan_t yyscanner;
- YY_BUFFER_STATE state;
-
+ yyscan_t yyscanner;
+ YY_BUFFER_STATE state;
+
yylex_init(&yyscanner);
- yyset_extra(context, yyscanner);
+ yyset_extra(context, yyscanner);
- state = yy_scan_string(rules_string, yyscanner);
-
- yyset_lineno(1, yyscanner);
+ state = yy_scan_string(rules_string, yyscanner);
+
+ yyset_lineno(1, yyscanner);
yyparse(yyscanner);
- yylex_destroy(yyscanner);
-
- return context->errors;
+ yylex_destroy(yyscanner);
+
+ return context->errors;
}
int parse_rules_file(FILE* rules_file, YARA_CONTEXT* context)
-{
- yyscan_t yyscanner;
-
+{
+ yyscan_t yyscanner;
+
yylex_init(&yyscanner);
- #ifdef DEBUG
- yyset_debug(1, yyscanner);
- #endif
-
- yyset_in(rules_file, yyscanner);
- yyset_extra(context, yyscanner);
-
+#ifdef DEBUG
+ yyset_debug(1, yyscanner);
+#endif
+
+ yyset_in(rules_file, yyscanner);
+ yyset_extra(context, yyscanner);
+
yyparse(yyscanner);
yylex_destroy(yyscanner);
- return context->errors;
+ return context->errors;
}
diff --git a/libyara/libyara.c b/libyara/libyara.c
index c5abeda..84588ea 100644
--- a/libyara/libyara.c
+++ b/libyara/libyara.c
@@ -366,11 +366,18 @@ int yr_push_file_name(YARA_CONTEXT* context, const char* file_name)
return ERROR_INCLUDES_CIRCULAR_REFERENCE;
}
}
-
- context->file_name_stack[context->file_name_stack_ptr] = yr_strdup(file_name);
- context->file_name_stack_ptr++;
-
- return ERROR_SUCCESS;
+
+ if (context->file_name_stack_ptr < MAX_INCLUDE_DEPTH)
+ {
+ context->file_name_stack[context->file_name_stack_ptr] = yr_strdup(file_name);
+ context->file_name_stack_ptr++;
+ return ERROR_SUCCESS;
+ }
+ else
+ {
+ context->last_result = ERROR_INCLUDE_DEPTH_EXCEEDED;
+ return ERROR_INCLUDE_DEPTH_EXCEEDED;
+ }
}
@@ -696,6 +703,8 @@ char* yr_get_error_message(YARA_CONTEXT* context, char* buffer, int buffer_size)
break;
case ERROR_INCLUDES_CIRCULAR_REFERENCE:
snprintf(buffer, buffer_size, "include circular reference");
+ case ERROR_INCLUDE_DEPTH_EXCEEDED:
+ snprintf(buffer, buffer_size, "too many levels of included rules");
break;
}
diff --git a/libyara/yara.h b/libyara/yara.h
index 0e508ec..cb9bb37 100644
--- a/libyara/yara.h
+++ b/libyara/yara.h
@@ -36,6 +36,8 @@ GNU General Public License for more details.
#endif
#define MAX_INCLUDE_DEPTH 16
+#define LEX_BUF_SIZE 1024
+
#define STRING_FLAGS_FOUND 0x01
#define STRING_FLAGS_REFERENCED 0x02
@@ -97,6 +99,7 @@ GNU General Public License for more details.
#define ERROR_INCORRECT_VARIABLE_TYPE 29
#define ERROR_COULD_NOT_ATTACH_TO_PROCESS 30
#define ERROR_VECTOR_TOO_LONG 31
+#define ERROR_INCLUDE_DEPTH_EXCEEDED 32
#define META_TYPE_INTEGER 1
#define META_TYPE_STRING 2
@@ -283,8 +286,8 @@ typedef struct _YARA_CONTEXT
int file_name_stack_ptr;
char last_error_extra_info[256];
-
- char lex_buf[256];
+
+ char lex_buf[LEX_BUF_SIZE];
char* lex_buf_ptr;
unsigned short lex_buf_len;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git
More information about the forensics-changes
mailing list