Files
yara/tests/test-string.c
T
Vincent Thiberville f9d87c68e4 fix error handling in string.to_int() (#1842)
* fix error handling in string.to_int()

Error handling in the to_int method of the new string module was not
properly done.

- errno was not reset prior to the call to strtoll, so YR_UNDEFINED
  could be returned if a prior call failed, but not the current one.
- overflow/underflow was not properly checked, as it returns LLONG_MIN
  or LLONG_MAX and not 0.

Instead, do what is recommended in the man page for strtol:
- set errno to 0 prior to the call
- check errno after the call

* Flesh out invalid cases for string.to_int

Ensure the behavior of string.to_int is the least surprising and
consistent across all OSes:

- return an error when the string is not entirely parsed (so "10p"
  fails to parse).
- return an error when the string has no digit whatsoever (avoiding
  parsing "foo" as 0).
- remove the evaluation differences on different libc implementations.

Fixes #1843

* validate value of base in string.to_int(string, base)

There seems to be implementation differences on invalid base values,
especially with cygwin. So validate that the base has a valid value
first.
2022-12-30 11:06:34 +01:00

144 lines
3.2 KiB
C

#include <stdio.h>
#include <yara.h>
#include "util.h"
int main(int argc, char** argv)
{
int result = 0;
YR_DEBUG_INITIALIZE();
YR_DEBUG_FPRINTF(1, stderr, "+ %s() { // in %s\n", __FUNCTION__, argv[0]);
yr_initialize();
assert_true_rule(
"import \"string\" \
rule test { \
condition: \
string.to_int(\"1234\") == 1234 \
}",
NULL);
assert_true_rule(
"import \"string\" \
rule test { \
condition: \
string.to_int(\"-1\") == -1 \
}",
NULL);
// Leading spaces and + are allowed.
assert_true_rule(
"import \"string\" \
rule test { \
condition: \
string.to_int(\" +1\") == 1 \
}",
NULL);
// Strings can be prefixed with 0x and will be interpreted as hexadecimal.
assert_true_rule(
"import \"string\" \
rule test { \
condition: \
string.to_int(\"0x10\") == 16 \
}",
NULL);
// Strings prefixed with 0 will be interpreted as octal.
assert_true_rule(
"import \"string\" \
rule test { \
condition: \
string.to_int(\"010\") == 8 \
}",
NULL);
assert_true_rule(
"import \"string\" \
rule test { \
condition: \
string.to_int(\"10\", 8) == 8 \
}",
NULL);
// Base 0 is a special case that tries to interpret the string by prefix, or
// default to decimal. We aren't doing anything special to get this, it is
// part of strtoll by default.
assert_true_rule(
"import \"string\" \
rule test { \
condition: \
string.to_int(\"010\", 0) == 8 and \
string.to_int(\"0x10\", 0) == 16 and \
string.to_int(\"10\", 0) == 10 \
}",
NULL);
// Test undefined cases
// on invalid base value
assert_true_rule(
"import \"string\" \
rule test { \
condition: \
not defined string.to_int(\"1\", -1) and \
not defined string.to_int(\"1\", 1) and \
not defined string.to_int(\"1\", 37) \
}",
NULL);
// on underflow or underflow
assert_true_rule(
"import \"string\" \
rule test { \
condition: \
not defined string.to_int(\"9223372036854775808\") \
}",
NULL);
assert_true_rule(
"import \"string\" \
rule test { \
condition: \
not defined string.to_int(\"-9223372036854775809\") \
}",
NULL);
// if parsing does not use all the string
assert_true_rule(
"import \"string\" \
rule test { \
condition: \
not defined string.to_int(\"FOO\") and \
not defined string.to_int(\"10A20\") \
}",
NULL);
// if parsing does not consume any digits
assert_true_rule(
"import \"string\" \
rule test { \
condition: \
not defined string.to_int(\"\") and \
not defined string.to_int(\" -\") and \
not defined string.to_int(\" +0x\") \
}",
NULL);
assert_true_rule(
"import \"string\" \
rule test { \
condition: \
string.length(\"AXS\\x00ERS\") == 7 \
}",
NULL);
yr_finalize();
YR_DEBUG_FPRINTF(
1, stderr, "} = %d // %s() in %s\n", result, __FUNCTION__, argv[0]);
return result;
}