[Forensics-changes] [yara] 21/407: Implement dictionaries
Hilko Bengen
bengen at moszumanska.debian.org
Sat Jul 1 10:27:59 UTC 2017
This is an automated email from the git hooks/post-receive script.
bengen pushed a commit to annotated tag v3.3.0
in repository yara.
commit 0bff0666fbfd9c6093d09b43c869a226b04274b1
Author: Victor Manuel Alvarez <vmalvarez at virustotal.com>
Date: Mon Sep 8 16:33:05 2014 +0200
Implement dictionaries
---
libyara/compiler.c | 4 +-
libyara/exec.c | 29 +++++-
libyara/grammar.c | 189 ++++++++++++++++++++----------------
libyara/grammar.y | 31 +++++-
libyara/include/yara/error.h | 2 +-
libyara/include/yara/exec.h | 1 +
libyara/include/yara/modules.h | 30 ++++++
libyara/include/yara/object.h | 13 +++
libyara/include/yara/types.h | 25 +++++
libyara/modules/tests.c | 6 ++
libyara/object.c | 215 +++++++++++++++++++++++++++++++++++------
yara-python/tests.py | 2 +
12 files changed, 429 insertions(+), 118 deletions(-)
diff --git a/libyara/compiler.c b/libyara/compiler.c
index 4c518e9..67a7f36 100644
--- a/libyara/compiler.c
+++ b/libyara/compiler.c
@@ -728,11 +728,11 @@ char* yr_compiler_get_error_message(
"\"%s\" is not a structure",
compiler->last_error_extra_info);
break;
- case ERROR_NOT_AN_ARRAY:
+ case ERROR_NOT_INDEXABLE:
snprintf(
buffer,
buffer_size,
- "\"%s\" is not a array",
+ "\"%s\" is not an array or dictionary",
compiler->last_error_extra_info);
break;
case ERROR_INVALID_FIELD_NAME:
diff --git a/libyara/exec.c b/libyara/exec.c
index a8aae87..7728580 100644
--- a/libyara/exec.c
+++ b/libyara/exec.c
@@ -429,10 +429,10 @@ int yr_execute_code(
break;
case OP_INDEX_ARRAY:
- pop(r1);
- pop(r2);
+ pop(r1); // index
+ pop(r2); // array
- if (r1 == UNDEFINED)
+ if (IS_UNDEFINED(r1))
{
push(UNDEFINED);
break;
@@ -449,6 +449,29 @@ int yr_execute_code(
break;
+ case OP_LOOKUP_DICT:
+ pop(r1); // key
+ pop(r2); // dictionary
+
+ if (IS_UNDEFINED(r1))
+ {
+ push(UNDEFINED);
+ break;
+ }
+
+ object = UINT64_TO_PTR(YR_OBJECT*, r2);
+ assert(object->type == OBJECT_TYPE_DICTIONARY);
+
+ object = yr_object_dict_get_item(
+ object, 0, UINT64_TO_PTR(const char*, r1));
+
+ if (object != NULL)
+ push(PTR_TO_UINT64(object));
+ else
+ push(UNDEFINED);
+
+ break;
+
case OP_CALL:
// r1 = number of arguments
diff --git a/libyara/grammar.c b/libyara/grammar.c
index 98f1105..bde75d0 100644
--- a/libyara/grammar.c
+++ b/libyara/grammar.c
@@ -637,14 +637,14 @@ static const yytype_uint16 yyrline[] =
244, 272, 276, 304, 309, 310, 315, 316, 322, 325,
343, 356, 393, 394, 399, 415, 428, 441, 458, 459,
464, 478, 477, 494, 511, 512, 517, 518, 519, 520,
- 525, 613, 662, 685, 725, 728, 750, 783, 828, 845,
- 854, 863, 878, 892, 906, 922, 937, 972, 936, 1083,
- 1082, 1159, 1165, 1171, 1177, 1185, 1194, 1203, 1212, 1221,
- 1248, 1275, 1302, 1306, 1314, 1315, 1320, 1342, 1354, 1370,
- 1369, 1375, 1384, 1385, 1390, 1395, 1404, 1405, 1409, 1417,
- 1421, 1431, 1444, 1456, 1468, 1480, 1492, 1504, 1516, 1526,
- 1549, 1564, 1579, 1601, 1638, 1648, 1658, 1668, 1678, 1688,
- 1698, 1708, 1718, 1728, 1738, 1748
+ 525, 613, 662, 712, 752, 755, 777, 810, 855, 872,
+ 881, 890, 905, 919, 933, 949, 964, 999, 963, 1110,
+ 1109, 1186, 1192, 1198, 1204, 1212, 1221, 1230, 1239, 1248,
+ 1275, 1302, 1329, 1333, 1341, 1342, 1347, 1369, 1381, 1397,
+ 1396, 1402, 1411, 1412, 1417, 1422, 1431, 1432, 1436, 1444,
+ 1448, 1458, 1471, 1483, 1495, 1507, 1519, 1531, 1543, 1553,
+ 1576, 1591, 1606, 1628, 1665, 1675, 1685, 1695, 1705, 1715,
+ 1725, 1735, 1745, 1755, 1765, 1775
};
#endif
@@ -2306,12 +2306,39 @@ yyreduce:
{
if ((yyvsp[(1) - (4)].object) != NULL && (yyvsp[(1) - (4)].object)->type == OBJECT_TYPE_ARRAY)
{
+ if ((yyvsp[(3) - (4)].expression).type != EXPRESSION_TYPE_INTEGER)
+ {
+ yr_compiler_set_error_extra_info(
+ compiler, "array indexes must be of integer type");
+ compiler->last_result = ERROR_WRONG_TYPE;
+ }
+
+ ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+
compiler->last_result = yr_parser_emit(
yyscanner,
OP_INDEX_ARRAY,
NULL);
- (yyval.object) = ((YR_OBJECT_ARRAY*) (yyvsp[(1) - (4)].object))->items->objects[0];
+ (yyval.object) = ((YR_OBJECT_ARRAY*) (yyvsp[(1) - (4)].object))->prototype_item;
+ }
+ else if ((yyvsp[(1) - (4)].object) != NULL && (yyvsp[(1) - (4)].object)->type == OBJECT_TYPE_DICTIONARY)
+ {
+ if ((yyvsp[(3) - (4)].expression).type != EXPRESSION_TYPE_STRING)
+ {
+ yr_compiler_set_error_extra_info(
+ compiler, "dictionary keys must be of string type");
+ compiler->last_result = ERROR_WRONG_TYPE;
+ }
+
+ ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+
+ compiler->last_result = yr_parser_emit(
+ yyscanner,
+ OP_LOOKUP_DICT,
+ NULL);
+
+ (yyval.object) = ((YR_OBJECT_DICTIONARY*) (yyvsp[(1) - (4)].object))->prototype_item;
}
else
{
@@ -2319,7 +2346,7 @@ yyreduce:
compiler,
(yyvsp[(1) - (4)].object)->identifier);
- compiler->last_result = ERROR_NOT_AN_ARRAY;
+ compiler->last_result = ERROR_NOT_INDEXABLE;
}
ERROR_IF(compiler->last_result != ERROR_SUCCESS);
@@ -2327,7 +2354,7 @@ yyreduce:
break;
case 43:
-#line 686 "grammar.y"
+#line 713 "grammar.y"
{
int args_count;
@@ -2365,14 +2392,14 @@ yyreduce:
break;
case 44:
-#line 725 "grammar.y"
+#line 752 "grammar.y"
{
(yyval.c_string) = yr_strdup("");
}
break;
case 45:
-#line 729 "grammar.y"
+#line 756 "grammar.y"
{
(yyval.c_string) = yr_malloc(MAX_FUNCTION_ARGS + 1);
@@ -2397,7 +2424,7 @@ yyreduce:
break;
case 46:
-#line 751 "grammar.y"
+#line 778 "grammar.y"
{
if (strlen((yyvsp[(1) - (3)].c_string)) == MAX_FUNCTION_ARGS)
{
@@ -2429,7 +2456,7 @@ yyreduce:
break;
case 47:
-#line 784 "grammar.y"
+#line 811 "grammar.y"
{
SIZED_STRING* sized_string = (yyvsp[(1) - (1)].sized_string);
RE* re;
@@ -2473,7 +2500,7 @@ yyreduce:
break;
case 48:
-#line 829 "grammar.y"
+#line 856 "grammar.y"
{
if ((yyvsp[(1) - (1)].expression).type == EXPRESSION_TYPE_STRING)
{
@@ -2490,7 +2517,7 @@ yyreduce:
break;
case 49:
-#line 846 "grammar.y"
+#line 873 "grammar.y"
{
compiler->last_result = yr_parser_emit_with_arg(
yyscanner, OP_PUSH, 1, NULL);
@@ -2502,7 +2529,7 @@ yyreduce:
break;
case 50:
-#line 855 "grammar.y"
+#line 882 "grammar.y"
{
compiler->last_result = yr_parser_emit_with_arg(
yyscanner, OP_PUSH, 0, NULL);
@@ -2514,7 +2541,7 @@ yyreduce:
break;
case 51:
-#line 864 "grammar.y"
+#line 891 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_STRING, "matches");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_REGEXP, "matches");
@@ -2532,7 +2559,7 @@ yyreduce:
break;
case 52:
-#line 879 "grammar.y"
+#line 906 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_STRING, "contains");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_STRING, "contains");
@@ -2549,7 +2576,7 @@ yyreduce:
break;
case 53:
-#line 893 "grammar.y"
+#line 920 "grammar.y"
{
int result = yr_parser_reduce_string_identifier(
yyscanner,
@@ -2566,7 +2593,7 @@ yyreduce:
break;
case 54:
-#line 907 "grammar.y"
+#line 934 "grammar.y"
{
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "at");
@@ -2585,7 +2612,7 @@ yyreduce:
break;
case 55:
-#line 923 "grammar.y"
+#line 950 "grammar.y"
{
compiler->last_result = yr_parser_reduce_string_identifier(
yyscanner,
@@ -2602,7 +2629,7 @@ yyreduce:
break;
case 56:
-#line 937 "grammar.y"
+#line 964 "grammar.y"
{
int var_index;
@@ -2640,7 +2667,7 @@ yyreduce:
break;
case 57:
-#line 972 "grammar.y"
+#line 999 "grammar.y"
{
int mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
int8_t* addr;
@@ -2678,7 +2705,7 @@ yyreduce:
break;
case 58:
-#line 1007 "grammar.y"
+#line 1034 "grammar.y"
{
int mem_offset;
@@ -2757,7 +2784,7 @@ yyreduce:
break;
case 59:
-#line 1083 "grammar.y"
+#line 1110 "grammar.y"
{
int mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
int8_t* addr;
@@ -2790,7 +2817,7 @@ yyreduce:
break;
case 60:
-#line 1113 "grammar.y"
+#line 1140 "grammar.y"
{
int mem_offset;
@@ -2840,7 +2867,7 @@ yyreduce:
break;
case 61:
-#line 1160 "grammar.y"
+#line 1187 "grammar.y"
{
yr_parser_emit(yyscanner, OP_OF, NULL);
@@ -2849,7 +2876,7 @@ yyreduce:
break;
case 62:
-#line 1166 "grammar.y"
+#line 1193 "grammar.y"
{
yr_parser_emit(yyscanner, OP_NOT, NULL);
@@ -2858,7 +2885,7 @@ yyreduce:
break;
case 63:
-#line 1172 "grammar.y"
+#line 1199 "grammar.y"
{
yr_parser_emit(yyscanner, OP_AND, NULL);
@@ -2867,7 +2894,7 @@ yyreduce:
break;
case 64:
-#line 1178 "grammar.y"
+#line 1205 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_BOOLEAN, "or");
@@ -2878,7 +2905,7 @@ yyreduce:
break;
case 65:
-#line 1186 "grammar.y"
+#line 1213 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "<");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "<");
@@ -2890,7 +2917,7 @@ yyreduce:
break;
case 66:
-#line 1195 "grammar.y"
+#line 1222 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, ">");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, ">");
@@ -2902,7 +2929,7 @@ yyreduce:
break;
case 67:
-#line 1204 "grammar.y"
+#line 1231 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "<=");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "<=");
@@ -2914,7 +2941,7 @@ yyreduce:
break;
case 68:
-#line 1213 "grammar.y"
+#line 1240 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, ">=");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, ">=");
@@ -2926,7 +2953,7 @@ yyreduce:
break;
case 69:
-#line 1222 "grammar.y"
+#line 1249 "grammar.y"
{
if ((yyvsp[(1) - (3)].expression).type != (yyvsp[(3) - (3)].expression).type)
{
@@ -2956,7 +2983,7 @@ yyreduce:
break;
case 70:
-#line 1249 "grammar.y"
+#line 1276 "grammar.y"
{
if ((yyvsp[(1) - (3)].expression).type != (yyvsp[(3) - (3)].expression).type)
{
@@ -2986,7 +3013,7 @@ yyreduce:
break;
case 71:
-#line 1276 "grammar.y"
+#line 1303 "grammar.y"
{
if ((yyvsp[(1) - (3)].expression).type != (yyvsp[(3) - (3)].expression).type)
{
@@ -3016,31 +3043,31 @@ yyreduce:
break;
case 72:
-#line 1303 "grammar.y"
+#line 1330 "grammar.y"
{
(yyval.expression) = (yyvsp[(1) - (1)].expression);
}
break;
case 73:
-#line 1307 "grammar.y"
+#line 1334 "grammar.y"
{
(yyval.expression) = (yyvsp[(2) - (3)].expression);
}
break;
case 74:
-#line 1314 "grammar.y"
+#line 1341 "grammar.y"
{ (yyval.integer) = INTEGER_SET_ENUMERATION; }
break;
case 75:
-#line 1315 "grammar.y"
+#line 1342 "grammar.y"
{ (yyval.integer) = INTEGER_SET_RANGE; }
break;
case 76:
-#line 1321 "grammar.y"
+#line 1348 "grammar.y"
{
if ((yyvsp[(2) - (6)].expression).type != EXPRESSION_TYPE_INTEGER)
{
@@ -3061,7 +3088,7 @@ yyreduce:
break;
case 77:
-#line 1343 "grammar.y"
+#line 1370 "grammar.y"
{
if ((yyvsp[(1) - (1)].expression).type != EXPRESSION_TYPE_INTEGER)
{
@@ -3076,7 +3103,7 @@ yyreduce:
break;
case 78:
-#line 1355 "grammar.y"
+#line 1382 "grammar.y"
{
if ((yyvsp[(3) - (3)].expression).type != EXPRESSION_TYPE_INTEGER)
{
@@ -3090,7 +3117,7 @@ yyreduce:
break;
case 79:
-#line 1370 "grammar.y"
+#line 1397 "grammar.y"
{
// Push end-of-list marker
yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
@@ -3098,7 +3125,7 @@ yyreduce:
break;
case 81:
-#line 1376 "grammar.y"
+#line 1403 "grammar.y"
{
yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
yr_parser_emit_pushes_for_strings(yyscanner, "$*");
@@ -3106,7 +3133,7 @@ yyreduce:
break;
case 84:
-#line 1391 "grammar.y"
+#line 1418 "grammar.y"
{
yr_parser_emit_pushes_for_strings(yyscanner, (yyvsp[(1) - (1)].c_string));
yr_free((yyvsp[(1) - (1)].c_string));
@@ -3114,7 +3141,7 @@ yyreduce:
break;
case 85:
-#line 1396 "grammar.y"
+#line 1423 "grammar.y"
{
yr_parser_emit_pushes_for_strings(yyscanner, (yyvsp[(1) - (1)].c_string));
yr_free((yyvsp[(1) - (1)].c_string));
@@ -3122,28 +3149,28 @@ yyreduce:
break;
case 87:
-#line 1406 "grammar.y"
+#line 1433 "grammar.y"
{
yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
}
break;
case 88:
-#line 1410 "grammar.y"
+#line 1437 "grammar.y"
{
yr_parser_emit_with_arg(yyscanner, OP_PUSH, 1, NULL);
}
break;
case 89:
-#line 1418 "grammar.y"
+#line 1445 "grammar.y"
{
(yyval.expression) = (yyvsp[(2) - (3)].expression);
}
break;
case 90:
-#line 1422 "grammar.y"
+#line 1449 "grammar.y"
{
compiler->last_result = yr_parser_emit(
yyscanner, OP_FILESIZE, NULL);
@@ -3156,7 +3183,7 @@ yyreduce:
break;
case 91:
-#line 1432 "grammar.y"
+#line 1459 "grammar.y"
{
yywarning(yyscanner,
"Using deprecated \"entrypoint\" keyword. Use the \"entry_point\" " "function from PE module instead.");
@@ -3172,7 +3199,7 @@ yyreduce:
break;
case 92:
-#line 1445 "grammar.y"
+#line 1472 "grammar.y"
{
CHECK_TYPE((yyvsp[(3) - (4)].expression), EXPRESSION_TYPE_INTEGER, "int8");
@@ -3187,7 +3214,7 @@ yyreduce:
break;
case 93:
-#line 1457 "grammar.y"
+#line 1484 "grammar.y"
{
CHECK_TYPE((yyvsp[(3) - (4)].expression), EXPRESSION_TYPE_INTEGER, "int16");
@@ -3202,7 +3229,7 @@ yyreduce:
break;
case 94:
-#line 1469 "grammar.y"
+#line 1496 "grammar.y"
{
CHECK_TYPE((yyvsp[(3) - (4)].expression), EXPRESSION_TYPE_INTEGER, "int32");
@@ -3217,7 +3244,7 @@ yyreduce:
break;
case 95:
-#line 1481 "grammar.y"
+#line 1508 "grammar.y"
{
CHECK_TYPE((yyvsp[(3) - (4)].expression), EXPRESSION_TYPE_INTEGER, "uint8");
@@ -3232,7 +3259,7 @@ yyreduce:
break;
case 96:
-#line 1493 "grammar.y"
+#line 1520 "grammar.y"
{
CHECK_TYPE((yyvsp[(3) - (4)].expression), EXPRESSION_TYPE_INTEGER, "uint16");
@@ -3247,7 +3274,7 @@ yyreduce:
break;
case 97:
-#line 1505 "grammar.y"
+#line 1532 "grammar.y"
{
CHECK_TYPE((yyvsp[(3) - (4)].expression), EXPRESSION_TYPE_INTEGER, "uint32");
@@ -3262,7 +3289,7 @@ yyreduce:
break;
case 98:
-#line 1517 "grammar.y"
+#line 1544 "grammar.y"
{
compiler->last_result = yr_parser_emit_with_arg(
yyscanner, OP_PUSH, (yyvsp[(1) - (1)].integer), NULL);
@@ -3275,7 +3302,7 @@ yyreduce:
break;
case 99:
-#line 1527 "grammar.y"
+#line 1554 "grammar.y"
{
SIZED_STRING* sized_string = (yyvsp[(1) - (1)].sized_string);
char* string;
@@ -3301,7 +3328,7 @@ yyreduce:
break;
case 100:
-#line 1550 "grammar.y"
+#line 1577 "grammar.y"
{
compiler->last_result = yr_parser_reduce_string_identifier(
yyscanner,
@@ -3319,7 +3346,7 @@ yyreduce:
break;
case 101:
-#line 1565 "grammar.y"
+#line 1592 "grammar.y"
{
compiler->last_result = yr_parser_reduce_string_identifier(
yyscanner,
@@ -3337,7 +3364,7 @@ yyreduce:
break;
case 102:
-#line 1580 "grammar.y"
+#line 1607 "grammar.y"
{
compiler->last_result = yr_parser_emit_with_arg(
yyscanner,
@@ -3362,7 +3389,7 @@ yyreduce:
break;
case 103:
-#line 1602 "grammar.y"
+#line 1629 "grammar.y"
{
if ((yyvsp[(1) - (1)].object) == (YR_OBJECT*) -1) // loop identifier
{
@@ -3402,7 +3429,7 @@ yyreduce:
break;
case 104:
-#line 1639 "grammar.y"
+#line 1666 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "+");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "+");
@@ -3415,7 +3442,7 @@ yyreduce:
break;
case 105:
-#line 1649 "grammar.y"
+#line 1676 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "-");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "-");
@@ -3428,7 +3455,7 @@ yyreduce:
break;
case 106:
-#line 1659 "grammar.y"
+#line 1686 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "*");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "*");
@@ -3441,7 +3468,7 @@ yyreduce:
break;
case 107:
-#line 1669 "grammar.y"
+#line 1696 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "\\");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "\\");
@@ -3454,7 +3481,7 @@ yyreduce:
break;
case 108:
-#line 1679 "grammar.y"
+#line 1706 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "%");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "%");
@@ -3467,7 +3494,7 @@ yyreduce:
break;
case 109:
-#line 1689 "grammar.y"
+#line 1716 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "^");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "^");
@@ -3480,7 +3507,7 @@ yyreduce:
break;
case 110:
-#line 1699 "grammar.y"
+#line 1726 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "^");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "^");
@@ -3493,7 +3520,7 @@ yyreduce:
break;
case 111:
-#line 1709 "grammar.y"
+#line 1736 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "|");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "|");
@@ -3506,7 +3533,7 @@ yyreduce:
break;
case 112:
-#line 1719 "grammar.y"
+#line 1746 "grammar.y"
{
CHECK_TYPE((yyvsp[(2) - (2)].expression), EXPRESSION_TYPE_INTEGER, "~");
@@ -3519,7 +3546,7 @@ yyreduce:
break;
case 113:
-#line 1729 "grammar.y"
+#line 1756 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "<<");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "<<");
@@ -3532,7 +3559,7 @@ yyreduce:
break;
case 114:
-#line 1739 "grammar.y"
+#line 1766 "grammar.y"
{
CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, ">>");
CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, ">>");
@@ -3545,7 +3572,7 @@ yyreduce:
break;
case 115:
-#line 1749 "grammar.y"
+#line 1776 "grammar.y"
{
(yyval.expression) = (yyvsp[(1) - (1)].expression);
}
@@ -3553,7 +3580,7 @@ yyreduce:
/* Line 1267 of yacc.c. */
-#line 3557 "grammar.c"
+#line 3584 "grammar.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -3767,6 +3794,6 @@ yyreturn:
}
-#line 1754 "grammar.y"
+#line 1781 "grammar.y"
diff --git a/libyara/grammar.y b/libyara/grammar.y
index b54e279..aabeb41 100644
--- a/libyara/grammar.y
+++ b/libyara/grammar.y
@@ -663,12 +663,39 @@ identifier
{
if ($1 != NULL && $1->type == OBJECT_TYPE_ARRAY)
{
+ if ($3.type != EXPRESSION_TYPE_INTEGER)
+ {
+ yr_compiler_set_error_extra_info(
+ compiler, "array indexes must be of integer type");
+ compiler->last_result = ERROR_WRONG_TYPE;
+ }
+
+ ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+
compiler->last_result = yr_parser_emit(
yyscanner,
OP_INDEX_ARRAY,
NULL);
- $$ = ((YR_OBJECT_ARRAY*) $1)->items->objects[0];
+ $$ = ((YR_OBJECT_ARRAY*) $1)->prototype_item;
+ }
+ else if ($1 != NULL && $1->type == OBJECT_TYPE_DICTIONARY)
+ {
+ if ($3.type != EXPRESSION_TYPE_STRING)
+ {
+ yr_compiler_set_error_extra_info(
+ compiler, "dictionary keys must be of string type");
+ compiler->last_result = ERROR_WRONG_TYPE;
+ }
+
+ ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+
+ compiler->last_result = yr_parser_emit(
+ yyscanner,
+ OP_LOOKUP_DICT,
+ NULL);
+
+ $$ = ((YR_OBJECT_DICTIONARY*) $1)->prototype_item;
}
else
{
@@ -676,7 +703,7 @@ identifier
compiler,
$1->identifier);
- compiler->last_result = ERROR_NOT_AN_ARRAY;
+ compiler->last_result = ERROR_NOT_INDEXABLE;
}
ERROR_IF(compiler->last_result != ERROR_SUCCESS);
diff --git a/libyara/include/yara/error.h b/libyara/include/yara/error.h
index c3f08a9..c1615e8 100644
--- a/libyara/include/yara/error.h
+++ b/libyara/include/yara/error.h
@@ -57,7 +57,7 @@ limitations under the License.
#define ERROR_INVALID_FIELD_NAME 33
#define ERROR_UNKNOWN_MODULE 34
#define ERROR_NOT_A_STRUCTURE 35
-#define ERROR_NOT_AN_ARRAY 36
+#define ERROR_NOT_INDEXABLE 36
#define ERROR_NOT_A_FUNCTION 37
#define ERROR_INVALID_FORMAT 38
#define ERROR_TOO_MANY_ARGUMENTS 39
diff --git a/libyara/include/yara/exec.h b/libyara/include/yara/exec.h
index 97b3012..5254425 100644
--- a/libyara/include/yara/exec.h
+++ b/libyara/include/yara/exec.h
@@ -83,6 +83,7 @@ limitations under the License.
#define OP_CONTAINS 53
#define OP_MATCHES 54
#define OP_IMPORT 55
+#define OP_LOOKUP_DICT 56
#define OPERATION(operator, op1, op2) \
diff --git a/libyara/include/yara/modules.h b/libyara/include/yara/modules.h
index 6b92364..fde28e0 100644
--- a/libyara/include/yara/modules.h
+++ b/libyara/include/yara/modules.h
@@ -122,6 +122,21 @@ limitations under the License.
}
+#define declare_integer_dictionary(name) { \
+ YR_OBJECT* dict; \
+ FAIL_ON_ERROR(yr_object_create( \
+ OBJECT_TYPE_DICTIONARY, \
+ name, \
+ stack[stack_top], \
+ &dict)); \
+ FAIL_ON_ERROR(yr_object_create( \
+ OBJECT_TYPE_INTEGER, \
+ name, \
+ dict, \
+ NULL)); \
+ }
+
+
#define declare_string(name) { \
FAIL_ON_ERROR(yr_object_create( \
OBJECT_TYPE_STRING, \
@@ -146,6 +161,21 @@ limitations under the License.
}
+#define declare_string_dictionary(name) { \
+ YR_OBJECT* dict; \
+ FAIL_ON_ERROR(yr_object_create( \
+ OBJECT_TYPE_DICTIONARY, \
+ name, \
+ stack[stack_top], \
+ &dict)); \
+ FAIL_ON_ERROR(yr_object_create( \
+ OBJECT_TYPE_STRING, \
+ name, \
+ dict, \
+ NULL)); \
+ }
+
+
#define declare_function(name, args_fmt, ret_fmt, func) { \
YR_OBJECT* function; \
FAIL_ON_ERROR(yr_object_function_create( \
diff --git a/libyara/include/yara/object.h b/libyara/include/yara/object.h
index bd09dd4..508babf 100644
--- a/libyara/include/yara/object.h
+++ b/libyara/include/yara/object.h
@@ -28,6 +28,7 @@ limitations under the License.
#define OBJECT_TYPE_ARRAY 4
#define OBJECT_TYPE_FUNCTION 5
#define OBJECT_TYPE_REGEXP 6
+#define OBJECT_TYPE_DICTIONARY 7
int yr_object_create(
@@ -105,6 +106,18 @@ int yr_object_array_set_item(
int index);
+YR_OBJECT* yr_object_dict_get_item(
+ YR_OBJECT* object,
+ int flags,
+ const char* key);
+
+
+int yr_object_dict_set_item(
+ YR_OBJECT* object,
+ YR_OBJECT* item,
+ const char* key);
+
+
int yr_object_structure_set_member(
YR_OBJECT* object,
YR_OBJECT* member);
diff --git a/libyara/include/yara/types.h b/libyara/include/yara/types.h
index 32c8186..ff25080 100644
--- a/libyara/include/yara/types.h
+++ b/libyara/include/yara/types.h
@@ -434,11 +434,21 @@ typedef struct _YR_OBJECT_STRUCTURE
typedef struct _YR_OBJECT_ARRAY
{
OBJECT_COMMON_FIELDS
+ YR_OBJECT* prototype_item;
struct _YR_ARRAY_ITEMS* items;
} YR_OBJECT_ARRAY;
+typedef struct _YR_OBJECT_DICTIONARY
+{
+ OBJECT_COMMON_FIELDS
+ YR_OBJECT* prototype_item;
+ struct _YR_DICTIONARY_ITEMS* items;
+
+} YR_OBJECT_DICTIONARY;
+
+
struct _YR_OBJECT_FUNCTION;
@@ -476,4 +486,19 @@ typedef struct _YR_ARRAY_ITEMS
} YR_ARRAY_ITEMS;
+typedef struct _YR_DICTIONARY_ITEMS
+{
+ int used;
+ int free;
+
+ struct {
+
+ char* key;
+ YR_OBJECT* obj;
+
+ } objects[1];
+
+} YR_DICTIONARY_ITEMS;
+
+
#endif
diff --git a/libyara/modules/tests.c b/libyara/modules/tests.c
index 4f4c9a9..d839a5f 100644
--- a/libyara/modules/tests.c
+++ b/libyara/modules/tests.c
@@ -41,6 +41,9 @@ begin_declarations;
declare_integer_array("integer_array");
declare_string_array("string_array");
+ declare_integer_dictionary("integer_dict");
+ declare_string_dictionary("string_dict");
+
begin_struct_array("struct_array");
declare_integer("i");
declare_string("s");
@@ -84,6 +87,9 @@ int module_load(
set_string("bar", module_object, "string_array[%i]", 1);
set_string("baz", module_object, "string_array[%i]", 2);
+ set_string("foo", module_object, "string_dict[%s]", "foo");
+ set_string("bar", module_object, "string_dict[\"bar\"]");
+
return ERROR_SUCCESS;
}
diff --git a/libyara/object.c b/libyara/object.c
index 5347c91..877330d 100644
--- a/libyara/object.c
+++ b/libyara/object.c
@@ -46,6 +46,9 @@ int yr_object_create(
case OBJECT_TYPE_ARRAY:
object_size = sizeof(YR_OBJECT_ARRAY);
break;
+ case OBJECT_TYPE_DICTIONARY:
+ object_size = sizeof(YR_OBJECT_DICTIONARY);
+ break;
case OBJECT_TYPE_INTEGER:
object_size = sizeof(YR_OBJECT_INTEGER);
break;
@@ -85,6 +88,11 @@ int yr_object_create(
break;
case OBJECT_TYPE_ARRAY:
((YR_OBJECT_ARRAY*) obj)->items = NULL;
+ ((YR_OBJECT_ARRAY*) obj)->prototype_item = NULL;
+ break;
+ case OBJECT_TYPE_DICTIONARY:
+ ((YR_OBJECT_DICTIONARY*) obj)->items = NULL;
+ ((YR_OBJECT_ARRAY*) obj)->prototype_item = NULL;
break;
case OBJECT_TYPE_INTEGER:
((YR_OBJECT_INTEGER*) obj)->value = UNDEFINED;
@@ -103,9 +111,10 @@ int yr_object_create(
if (parent != NULL)
{
- assert( parent->type == OBJECT_TYPE_STRUCTURE ||
- parent->type == OBJECT_TYPE_ARRAY ||
- parent->type == OBJECT_TYPE_FUNCTION);
+ assert(parent->type == OBJECT_TYPE_STRUCTURE ||
+ parent->type == OBJECT_TYPE_ARRAY ||
+ parent->type == OBJECT_TYPE_DICTIONARY ||
+ parent->type == OBJECT_TYPE_FUNCTION);
switch(parent->type)
{
@@ -116,9 +125,11 @@ int yr_object_create(
break;
case OBJECT_TYPE_ARRAY:
- FAIL_ON_ERROR_WITH_CLEANUP(
- yr_object_array_set_item(parent, obj, 0),
- yr_free(obj));
+ ((YR_OBJECT_ARRAY*) parent)->prototype_item = obj;
+ break;
+
+ case OBJECT_TYPE_DICTIONARY:
+ ((YR_OBJECT_DICTIONARY*) parent)->prototype_item = obj;
break;
}
}
@@ -234,6 +245,7 @@ void yr_object_destroy(
YR_STRUCTURE_MEMBER* member;
YR_STRUCTURE_MEMBER* next_member;
YR_ARRAY_ITEMS* array_items;
+ YR_DICTIONARY_ITEMS* dict_items;
RE* re;
int i;
@@ -266,15 +278,42 @@ void yr_object_destroy(
break;
case OBJECT_TYPE_ARRAY:
+ if (((YR_OBJECT_ARRAY*) object)->prototype_item != NULL)
+ yr_free(((YR_OBJECT_ARRAY*) object)->prototype_item);
+
array_items = ((YR_OBJECT_ARRAY*) object)->items;
- for (i = 0; i < array_items->count; i++)
- if (array_items->objects[i] != NULL)
- yr_object_destroy(array_items->objects[i]);
+ if (array_items != NULL)
+ {
+ for (i = 0; i < array_items->count; i++)
+ if (array_items->objects[i] != NULL)
+ yr_object_destroy(array_items->objects[i]);
+ }
yr_free(array_items);
break;
+ case OBJECT_TYPE_DICTIONARY:
+ if (((YR_OBJECT_DICTIONARY*) object)->prototype_item != NULL)
+ yr_free(((YR_OBJECT_DICTIONARY*) object)->prototype_item);
+
+ dict_items = ((YR_OBJECT_DICTIONARY*) object)->items;
+
+ if (dict_items != NULL)
+ {
+ for (i = 0; i < dict_items->used; i++)
+ {
+ if (dict_items->objects[i].key != NULL)
+ yr_free(dict_items->objects[i].key);
+
+ if (dict_items->objects[i].obj != NULL)
+ yr_object_destroy(dict_items->objects[i].obj);
+ }
+ }
+
+ yr_free(dict_items);
+ break;
+
case OBJECT_TYPE_FUNCTION:
yr_object_destroy(((YR_OBJECT_FUNCTION*) object)->return_obj);
break;
@@ -317,7 +356,9 @@ YR_OBJECT* _yr_object_lookup(
YR_OBJECT* obj = object;
const char* p = pattern;
- char field_name[256];
+ const char* key;
+
+ char str[256];
int i;
int index;
@@ -326,17 +367,17 @@ YR_OBJECT* _yr_object_lookup(
{
i = 0;
- while(*p != '\0' && *p != '.' && *p != '[')
+ while(*p != '\0' && *p != '.' && *p != '[' && i < sizeof(str))
{
- field_name[i++] = *p++;
+ str[i++] = *p++;
}
- field_name[i] = '\0';
+ str[i] = '\0';
if (obj->type != OBJECT_TYPE_STRUCTURE)
return NULL;
- obj = yr_object_lookup_field(obj, field_name);
+ obj = yr_object_lookup_field(obj, str);
if (obj == NULL)
return NULL;
@@ -347,20 +388,37 @@ YR_OBJECT* _yr_object_lookup(
if (*p == '%')
{
- if (*++p == 'i')
- {
- index = va_arg(args, int);
- p++;
- }
- else
+ p++;
+
+ switch(*p++)
{
- return NULL;
+ case 'i':
+ index = va_arg(args, int);
+ break;
+ case 's':
+ key = va_arg(args, const char*);
+ break;
+
+ default:
+ return NULL;
}
}
else if (*p >= '0' && *p <= '9')
{
index = strtol(p, (char**) &p, 10);
}
+ else if (*p == '"')
+ {
+ i = 0;
+ p++; // skip the opening quotation mark
+
+ while (*p != '"' && *p != '\0' && i < sizeof(str))
+ str[i++] = *p++;
+
+ str[i] = '\0';
+ p++; // skip the closing quotation mark
+ key = str;
+ }
else
{
return NULL;
@@ -369,7 +427,16 @@ YR_OBJECT* _yr_object_lookup(
assert(*p++ == ']');
assert(*p == '.' || *p == '\0');
- obj = yr_object_array_get_item(obj, flags, index);
+ switch(obj->type)
+ {
+ case OBJECT_TYPE_ARRAY:
+ obj = yr_object_array_get_item(obj, flags, index);
+ break;
+
+ case OBJECT_TYPE_DICTIONARY:
+ obj = yr_object_dict_get_item(obj, flags, key);
+ break;
+ }
}
if (*p == '\0')
@@ -518,20 +585,18 @@ YR_OBJECT* yr_object_array_get_item(
int index)
{
YR_OBJECT* result = NULL;
- YR_ARRAY_ITEMS* array_items;
+ YR_OBJECT_ARRAY* array;
assert(object->type == OBJECT_TYPE_ARRAY);
- array_items = ((YR_OBJECT_ARRAY*) object)->items;
+ array = (YR_OBJECT_ARRAY*) object;
- assert(array_items != NULL);
-
- if (array_items->count > index)
- result = array_items->objects[index];
+ if (array->items != NULL && array->items->count > index)
+ result = array->items->objects[index];
if (result == NULL && flags & OBJECT_CREATE)
{
- yr_object_copy(array_items->objects[0], &result);
+ yr_object_copy(array->prototype_item, &result);
if (result != NULL)
yr_object_array_set_item(object, result, index);
@@ -592,6 +657,98 @@ int yr_object_array_set_item(
}
+YR_OBJECT* yr_object_dict_get_item(
+ YR_OBJECT* object,
+ int flags,
+ const char* key)
+{
+ YR_OBJECT* result = NULL;
+ YR_OBJECT_DICTIONARY* dict;
+
+ assert(object->type == OBJECT_TYPE_DICTIONARY);
+
+ dict = (YR_OBJECT_DICTIONARY*) object;
+
+ if (dict->items != NULL)
+ {
+ for (int i = 0; i < dict->items->used; i++)
+ {
+ if (strcmp(dict->items->objects[i].key, key) == 0)
+ result = dict->items->objects[i].obj;
+ }
+ }
+
+ if (result == NULL && flags & OBJECT_CREATE)
+ {
+ yr_object_copy(dict->prototype_item, &result);
+
+ if (result != NULL)
+ yr_object_dict_set_item(object, result, key);
+ }
+
+ return result;
+}
+
+
+int yr_object_dict_set_item(
+ YR_OBJECT* object,
+ YR_OBJECT* item,
+ const char* key)
+{
+ YR_OBJECT_DICTIONARY* dict;
+
+ int i;
+ int count;
+
+ assert(object->type == OBJECT_TYPE_DICTIONARY);
+
+ dict = ((YR_OBJECT_DICTIONARY*) object);
+
+ if (dict->items == NULL)
+ {
+ count = 64;
+
+ dict->items = yr_malloc(
+ sizeof(YR_DICTIONARY_ITEMS) + count * sizeof(dict->items->objects[0]));
+
+ if (dict->items == NULL)
+ return ERROR_INSUFICIENT_MEMORY;
+
+ memset(dict->items->objects, 0, count * sizeof(dict->items->objects[0]));
+
+ dict->items->free = count;
+ dict->items->used = 0;
+ }
+ else if (dict->items->free == 0)
+ {
+ count = dict->items->used * 2;
+ dict->items = yr_realloc(
+ dict->items,
+ sizeof(YR_DICTIONARY_ITEMS) + count * sizeof(dict->items->objects[0]));
+
+ if (dict->items == NULL)
+ return ERROR_INSUFICIENT_MEMORY;
+
+ for (i = dict->items->used; i < count; i++)
+ {
+ dict->items->objects[i].key = NULL;
+ dict->items->objects[i].obj = NULL;
+ }
+
+ dict->items->free = dict->items->used;
+ }
+
+ item->parent = object;
+
+ dict->items->objects[dict->items->used].key = yr_strdup(key);
+ dict->items->objects[dict->items->used].obj = item;
+
+ dict->items->used++;
+
+ return ERROR_SUCCESS;
+}
+
+
int64_t yr_object_get_integer(
YR_OBJECT* object,
char* field,
diff --git a/yara-python/tests.py b/yara-python/tests.py
index 648a7d3..33de8f1 100644
--- a/yara-python/tests.py
+++ b/yara-python/tests.py
@@ -707,6 +707,8 @@ class TestYara(unittest.TestCase):
'import "tests" rule test { condition: tests.integer_array[1] == 1}',
'import "tests" rule test { condition: tests.string_array[0] == "foo"}',
'import "tests" rule test { condition: tests.string_array[2] == "baz"}',
+ 'import "tests" rule test { condition: tests.string_dict["foo"] == "foo"}',
+ 'import "tests" rule test { condition: tests.string_dict["bar"] == "bar"}',
'import "tests" rule test { condition: tests.sum(1,1) == 2}',
])
--
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