diff --git a/docs/capi.rst b/docs/capi.rst index 104262bde1..245bcca862 100644 --- a/docs/capi.rst +++ b/docs/capi.rst @@ -69,10 +69,14 @@ However, if you want to fetch the imported rules from another source (eg: from a database or remote service), a callback function can be set with :c:func:`yr_compiler_set_include_callback`. The callback receives the following parameters: - *``include_name``: name of the requested file. - *``calling_rule_filename``: the requesting file name (NULL if not a file). - *``calling_rule_namespace``: namespace (NULL if undefined). -And should return the requested file as a string. + * ``include_name``: name of the requested file. + * ``calling_rule_filename``: the requesting file name (NULL if not a file). + * ``calling_rule_namespace``: namespace (NULL if undefined). + * ``user_data`` pointer is the same you passed to + :c:func:`yr_compiler_set_include_callback`. +It should return the requested file's content as a string. The memory for this string +should be allocated by the callback function (yr_malloc can be used) but will +be automatically freed by the yara compiler. The callback function has the following prototype: @@ -695,6 +699,31 @@ Functions Enables the specified rule. After being disabled with :c:func:`yr_rule_disable` a rule can be enabled again by using this function. +.. c:function:: void* yr_calloc(size_t count, size_t size); + + Cross-platform wrapper for HeapAlloc on Windows and calloc on other platforms. + +.. c:function:: void* yr_malloc(size_t size); + + Cross-platform wrapper for HeapAlloc on Windows and malloc on other platforms. + +.. c:function:: void* yr_realloc(void* ptr, size_t size); + + Cross-platform wrapper for HeapReAlloc on Windows and realloc on other platforms. + +.. c:function:: void yr_free(void* ptr); + + Cross-platform wrapper for HeapFree on Windows and free on other platforms. + +.. c:function:: char* yr_strdup(const char *str); + + Allocates a new buffer the same size as str and copies str to the new buffer. + +.. c:function:: char* yr_strdup(const char *str, size_t n); + + Allocates a new buffer of size n and copies the n first character of str. + + Error codes ----------- diff --git a/libyara/compiler.c b/libyara/compiler.c index a7e4ca5119..f405ec3574 100644 --- a/libyara/compiler.c +++ b/libyara/compiler.c @@ -189,7 +189,7 @@ YR_API void yr_compiler_set_include_callback( void* user_data) { compiler->include_callback = include_callback; - compiler->user_data = user_data; + compiler->incl_clbk_user_data = user_data; } diff --git a/libyara/include/yara.h b/libyara/include/yara.h index 3a35518663..a627e90bf9 100644 --- a/libyara/include/yara.h +++ b/libyara/include/yara.h @@ -39,5 +39,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "yara/error.h" #include "yara/stream.h" #include "yara/hash.h" +#include "yara/mem.h" #endif diff --git a/libyara/include/yara/compiler.h b/libyara/include/yara/compiler.h index 93a6263cc8..5302442311 100644 --- a/libyara/include/yara/compiler.h +++ b/libyara/include/yara/compiler.h @@ -121,6 +121,7 @@ typedef struct _YR_COMPILER char include_base_dir[MAX_PATH]; void* user_data; + void* incl_clbk_user_data; YR_COMPILER_CALLBACK_FUNC callback; YR_COMPILER_INCLUDE_CALLBACK_FUNC include_callback; diff --git a/libyara/include/yara/mem.h b/libyara/include/yara/mem.h index ff7dc3ec7e..a556fcb583 100644 --- a/libyara/include/yara/mem.h +++ b/libyara/include/yara/mem.h @@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define YR_MEM_H #include +#include #ifdef DMALLOC @@ -45,24 +46,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #else -void* yr_calloc( +YR_API void* yr_calloc( size_t count, size_t size); -void* yr_malloc( +YR_API void* yr_malloc( size_t size); -void* yr_realloc( +YR_API void* yr_realloc( void* ptr, size_t size); -void yr_free( +YR_API void yr_free( void *ptr); -char* yr_strdup( +YR_API char* yr_strdup( const char *str); -char* yr_strndup( +YR_API char* yr_strndup( const char *str, size_t n); #endif diff --git a/libyara/lexer.c b/libyara/lexer.c index b5d9108b21..68fd25b268 100644 --- a/libyara/lexer.c +++ b/libyara/lexer.c @@ -1458,10 +1458,20 @@ YY_RULE_SETUP } else { - const char* res = compiler->include_callback(yyextra->lex_buf, current_file_name, compiler->current_namespace->name, compiler->user_data); + const char* res = compiler->include_callback( + yyextra->lex_buf, + current_file_name, + compiler->current_namespace->name, + compiler->incl_clbk_user_data); + if (res != NULL) { - int error_code = _yr_compiler_push_file_name(compiler, yyextra->lex_buf); + const char* res_dup = yr_strdup(res); + yr_free((void*) res); + res = NULL; + + int error_code = _yr_compiler_push_file_name( compiler, + yyextra->lex_buf); if (error_code != ERROR_SUCCESS) { @@ -1474,16 +1484,24 @@ YY_RULE_SETUP yyerror(yyscanner, compiler, "includes depth exceeded"); } + yr_free((void*) res_dup); + res_dup = NULL; yyterminate(); } + // Workaround for flex issue: https://github.com/westes/flex/issues/58 yara_yypush_buffer_state(YY_CURRENT_BUFFER,yyscanner); - yara_yy_scan_string(res,yyscanner); + yara_yy_scan_string(res_dup,yyscanner); + + yr_free((void*) res_dup); + res_dup = NULL; } else { - snprintf(buffer, sizeof(buffer), - "'include_callback' failed to return rules contained in '%s'", yyextra->lex_buf); + snprintf( buffer, + sizeof(buffer), + "'include_callback' failed to return rules contained in '%s'", + yyextra->lex_buf); yyerror(yyscanner, compiler, buffer); } @@ -1503,7 +1521,7 @@ case YY_STATE_EOF(str): case YY_STATE_EOF(regexp): case YY_STATE_EOF(include): case YY_STATE_EOF(comment): -#line 336 "lexer.l" +#line 354 "lexer.l" { YR_COMPILER* compiler = yara_yyget_extra(yyscanner); @@ -1539,7 +1557,7 @@ case YY_STATE_EOF(comment): YY_BREAK case 44: YY_RULE_SETUP -#line 370 "lexer.l" +#line 388 "lexer.l" { yylval->c_string = yr_strdup(yytext); @@ -1555,7 +1573,7 @@ YY_RULE_SETUP YY_BREAK case 45: YY_RULE_SETUP -#line 384 "lexer.l" +#line 402 "lexer.l" { yylval->c_string = yr_strdup(yytext); @@ -1571,7 +1589,7 @@ YY_RULE_SETUP YY_BREAK case 46: YY_RULE_SETUP -#line 398 "lexer.l" +#line 416 "lexer.l" { yylval->c_string = yr_strdup(yytext); @@ -1588,7 +1606,7 @@ YY_RULE_SETUP YY_BREAK case 47: YY_RULE_SETUP -#line 413 "lexer.l" +#line 431 "lexer.l" { yylval->c_string = yr_strdup(yytext); @@ -1605,7 +1623,7 @@ YY_RULE_SETUP YY_BREAK case 48: YY_RULE_SETUP -#line 428 "lexer.l" +#line 446 "lexer.l" { yylval->c_string = yr_strdup(yytext); @@ -1622,7 +1640,7 @@ YY_RULE_SETUP YY_BREAK case 49: YY_RULE_SETUP -#line 443 "lexer.l" +#line 461 "lexer.l" { char* text = yytext; @@ -1663,7 +1681,7 @@ YY_RULE_SETUP YY_BREAK case 50: YY_RULE_SETUP -#line 482 "lexer.l" +#line 500 "lexer.l" { if (strlen(yytext) > 128) @@ -1684,7 +1702,7 @@ YY_RULE_SETUP YY_BREAK case 51: YY_RULE_SETUP -#line 501 "lexer.l" +#line 519 "lexer.l" { #ifdef _MSC_VER @@ -1706,7 +1724,7 @@ YY_RULE_SETUP YY_BREAK case 52: YY_RULE_SETUP -#line 520 "lexer.l" +#line 538 "lexer.l" { yylval->double_ = atof(yytext); return _DOUBLE_; @@ -1714,7 +1732,7 @@ YY_RULE_SETUP YY_BREAK case 53: YY_RULE_SETUP -#line 525 "lexer.l" +#line 543 "lexer.l" { yylval->integer = xtoi(yytext + 2); return _NUMBER_; @@ -1722,7 +1740,7 @@ YY_RULE_SETUP YY_BREAK case 54: YY_RULE_SETUP -#line 530 "lexer.l" +#line 548 "lexer.l" { yylval->integer = otoi(yytext + 2); return _NUMBER_; @@ -1730,7 +1748,7 @@ YY_RULE_SETUP YY_BREAK case 55: YY_RULE_SETUP -#line 536 "lexer.l" +#line 554 "lexer.l" { /* saw closing quote - all done */ ALLOC_SIZED_STRING(s, yyextra->lex_buf_len); @@ -1746,7 +1764,7 @@ YY_RULE_SETUP YY_BREAK case 56: YY_RULE_SETUP -#line 550 "lexer.l" +#line 568 "lexer.l" { LEX_CHECK_SPACE_OK("\t", yyextra->lex_buf_len, LEX_BUF_SIZE); @@ -1756,7 +1774,7 @@ YY_RULE_SETUP YY_BREAK case 57: YY_RULE_SETUP -#line 558 "lexer.l" +#line 576 "lexer.l" { LEX_CHECK_SPACE_OK("\n", yyextra->lex_buf_len, LEX_BUF_SIZE); @@ -1766,7 +1784,7 @@ YY_RULE_SETUP YY_BREAK case 58: YY_RULE_SETUP -#line 566 "lexer.l" +#line 584 "lexer.l" { LEX_CHECK_SPACE_OK("\"", yyextra->lex_buf_len, LEX_BUF_SIZE); @@ -1776,7 +1794,7 @@ YY_RULE_SETUP YY_BREAK case 59: YY_RULE_SETUP -#line 574 "lexer.l" +#line 592 "lexer.l" { LEX_CHECK_SPACE_OK("\\", yyextra->lex_buf_len, LEX_BUF_SIZE); @@ -1786,7 +1804,7 @@ YY_RULE_SETUP YY_BREAK case 60: YY_RULE_SETUP -#line 582 "lexer.l" +#line 600 "lexer.l" { int result; @@ -1799,13 +1817,13 @@ YY_RULE_SETUP YY_BREAK case 61: YY_RULE_SETUP -#line 593 "lexer.l" +#line 611 "lexer.l" { YYTEXT_TO_BUFFER; } YY_BREAK case 62: /* rule 62 can match eol */ YY_RULE_SETUP -#line 596 "lexer.l" +#line 614 "lexer.l" { yyerror(yyscanner, compiler, "unterminated string"); @@ -1815,7 +1833,7 @@ YY_RULE_SETUP case 63: /* rule 63 can match eol */ YY_RULE_SETUP -#line 602 "lexer.l" +#line 620 "lexer.l" { yyerror(yyscanner, compiler, "illegal escape sequence"); @@ -1824,7 +1842,7 @@ YY_RULE_SETUP YY_BREAK case 64: YY_RULE_SETUP -#line 609 "lexer.l" +#line 627 "lexer.l" { if (yyextra->lex_buf_len > 0) @@ -1853,7 +1871,7 @@ YY_RULE_SETUP YY_BREAK case 65: YY_RULE_SETUP -#line 636 "lexer.l" +#line 654 "lexer.l" { LEX_CHECK_SPACE_OK("/", yyextra->lex_buf_len, LEX_BUF_SIZE); @@ -1863,7 +1881,7 @@ YY_RULE_SETUP YY_BREAK case 66: YY_RULE_SETUP -#line 644 "lexer.l" +#line 662 "lexer.l" { LEX_CHECK_SPACE_OK("\\.", yyextra->lex_buf_len, LEX_BUF_SIZE); @@ -1881,13 +1899,13 @@ YY_RULE_SETUP YY_BREAK case 67: YY_RULE_SETUP -#line 660 "lexer.l" +#line 678 "lexer.l" { YYTEXT_TO_BUFFER; } YY_BREAK case 68: /* rule 68 can match eol */ YY_RULE_SETUP -#line 663 "lexer.l" +#line 681 "lexer.l" { yyerror(yyscanner, compiler, "unterminated regular expression"); @@ -1896,7 +1914,7 @@ YY_RULE_SETUP YY_BREAK case 69: YY_RULE_SETUP -#line 670 "lexer.l" +#line 688 "lexer.l" { yyextra->lex_buf_ptr = yyextra->lex_buf; @@ -1906,7 +1924,7 @@ YY_RULE_SETUP YY_BREAK case 70: YY_RULE_SETUP -#line 678 "lexer.l" +#line 696 "lexer.l" { yyextra->lex_buf_ptr = yyextra->lex_buf; @@ -1917,7 +1935,7 @@ YY_RULE_SETUP case 71: /* rule 71 can match eol */ YY_RULE_SETUP -#line 686 "lexer.l" +#line 704 "lexer.l" { // Match hex-digits with whitespace or comments. The latter are stripped // out by hex_lexer.l @@ -1933,12 +1951,12 @@ YY_RULE_SETUP case 72: /* rule 72 can match eol */ YY_RULE_SETUP -#line 699 "lexer.l" +#line 717 "lexer.l" /* skip whitespace */ YY_BREAK case 73: YY_RULE_SETUP -#line 701 "lexer.l" +#line 719 "lexer.l" { if (yytext[0] >= 32 && yytext[0] < 127) @@ -1954,10 +1972,10 @@ YY_RULE_SETUP YY_BREAK case 74: YY_RULE_SETUP -#line 714 "lexer.l" +#line 732 "lexer.l" ECHO; YY_BREAK -#line 1961 "lexer.c" +#line 1979 "lexer.c" case YY_END_OF_BUFFER: { @@ -3106,7 +3124,7 @@ void yara_yyfree (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 714 "lexer.l" +#line 732 "lexer.l" diff --git a/libyara/lexer.l b/libyara/lexer.l index d4a29d65c2..84830f7453 100644 --- a/libyara/lexer.l +++ b/libyara/lexer.l @@ -292,10 +292,20 @@ include[ \t]+\" { } else { - const char* res = compiler->include_callback(yyextra->lex_buf, current_file_name, compiler->current_namespace->name, compiler->user_data); + const char* res = compiler->include_callback( + yyextra->lex_buf, + current_file_name, + compiler->current_namespace->name, + compiler->incl_clbk_user_data); + if (res != NULL) { - int error_code = _yr_compiler_push_file_name(compiler, yyextra->lex_buf); + const char* res_dup = yr_strdup(res); + yr_free((void*) res); + res = NULL; + + int error_code = _yr_compiler_push_file_name( compiler, + yyextra->lex_buf); if (error_code != ERROR_SUCCESS) { @@ -308,16 +318,24 @@ include[ \t]+\" { yyerror(yyscanner, compiler, "includes depth exceeded"); } + yr_free((void*) res_dup); + res_dup = NULL; yyterminate(); } + // Workaround for flex issue: https://github.com/westes/flex/issues/58 yypush_buffer_state(YY_CURRENT_BUFFER, yyscanner); - yy_scan_string(res, yyscanner); + yy_scan_string(res_dup, yyscanner); + + yr_free((void*) res_dup); + res_dup = NULL; } else { - snprintf(buffer, sizeof(buffer), - "'include_callback' failed to return rules contained in '%s'", yyextra->lex_buf); + snprintf( buffer, + sizeof(buffer), + "'include_callback' failed to return rules contained in '%s'", + yyextra->lex_buf); yyerror(yyscanner, compiler, buffer); } diff --git a/libyara/mem.c b/libyara/mem.c index 53a151fe69..55b0d8acca 100644 --- a/libyara/mem.c +++ b/libyara/mem.c @@ -27,7 +27,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#include #if defined(_WIN32) || defined(__CYGWIN__) @@ -58,31 +58,31 @@ int yr_heap_free(void) } -void* yr_calloc(size_t count, size_t size) +YR_API void* yr_calloc(size_t count, size_t size) { return (void*) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, count * size); } -void* yr_malloc(size_t size) +YR_API void* yr_malloc(size_t size) { return (void*) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, size); } -void* yr_realloc(void* ptr, size_t size) +YR_API void* yr_realloc(void* ptr, size_t size) { return (void*) HeapReAlloc(hHeap, HEAP_ZERO_MEMORY, ptr, size); } -void yr_free(void* ptr) +YR_API void yr_free(void* ptr) { HeapFree(hHeap, 0, ptr); } -char* yr_strdup(const char *str) +YR_API char* yr_strdup(const char *str) { size_t len = strlen(str); char *dup = (char*) yr_malloc(len + 1); @@ -97,7 +97,7 @@ char* yr_strdup(const char *str) } -char* yr_strndup(const char *str, size_t n) +YR_API char* yr_strndup(const char *str, size_t n) { size_t len = strnlen(str, n); char *dup = (char*) yr_malloc(len + 1); @@ -133,37 +133,37 @@ int yr_heap_free(void) } -void* yr_calloc(size_t count, size_t size) +YR_API void* yr_calloc(size_t count, size_t size) { return calloc(count, size); } -void* yr_malloc(size_t size) +YR_API void* yr_malloc(size_t size) { return malloc(size); } -void* yr_realloc(void* ptr, size_t size) +YR_API void* yr_realloc(void* ptr, size_t size) { return realloc(ptr, size); } -void yr_free(void *ptr) +YR_API void yr_free(void *ptr) { free(ptr); } -char* yr_strdup(const char *str) +YR_API char* yr_strdup(const char *str) { return strdup(str); } -char* yr_strndup(const char *str, size_t n) +YR_API char* yr_strndup(const char *str, size_t n) { return strndup(str, n); }