ok, this one might really be a bit too big for 2.1

Give all kinds of errors when encountering invalid numbers (like out-of-range-warnings, etc).
This commit is contained in:
Bernhard Amann 2012-08-26 22:00:37 -07:00
parent 7e46936728
commit f133e8808a
7 changed files with 122 additions and 8 deletions

View file

@ -11,6 +11,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
using namespace input::reader;
using threading::Value;
@ -209,6 +210,34 @@ bool Ascii::GetLine(string& str)
return false;
}
bool Ascii::CheckNumberError(const string & s, const char * end)
{
if ( s.length() == 0 )
{
Error("Got empty string for number field");
return true;
}
if ( end == s.c_str() ) {
Error(Fmt("String '%s' contained no parseable number", s.c_str()));
return true;
}
if ( *end != '\0' )
Error(Fmt("Number '%s' contained non-numeric trailing characters. Ignored trailing characters '%s'", s.c_str(), end));
if ( errno == EINVAL )
{
Error(Fmt("String '%s' could not be converted to a number", s.c_str()));
return true;
}
else if ( errno == ERANGE )
Error(Fmt("Number '%s' out of supported range. Number was truncated", s.c_str()));
return false;
}
Value* Ascii::EntryToVal(string s, FieldMapping field)
{
@ -216,6 +245,8 @@ Value* Ascii::EntryToVal(string s, FieldMapping field)
return new Value(field.type, false);
Value* val = new Value(field.type, true);
char* end;
errno = 0;
switch ( field.type ) {
case TYPE_ENUM:
@ -239,22 +270,31 @@ Value* Ascii::EntryToVal(string s, FieldMapping field)
break;
case TYPE_INT:
val->val.int_val = strtoll(s.c_str(), (char**) NULL, 10);
val->val.int_val = strtoll(s.c_str(), &end, 10);
if ( CheckNumberError(s, end) )
return 0;
break;
case TYPE_DOUBLE:
case TYPE_TIME:
case TYPE_INTERVAL:
val->val.double_val = atof(s.c_str());
val->val.double_val = strtod(s.c_str(), &end);
if ( CheckNumberError(s, end) )
return 0;
break;
case TYPE_COUNT:
case TYPE_COUNTER:
val->val.uint_val = strtoull(s.c_str(),(char**) NULL, 10);
val->val.uint_val = strtoull(s.c_str(), &end, 10);
if ( CheckNumberError(s, end) )
return 0;
break;
case TYPE_PORT:
val->val.port_val.port = atoi(s.c_str());
val->val.port_val.port = strtoull(s.c_str(), &end, 10);
if ( CheckNumberError(s, end) )
return 0;
val->val.port_val.proto = TRANSPORT_UNKNOWN;
break;
@ -268,9 +308,12 @@ Value* Ascii::EntryToVal(string s, FieldMapping field)
return 0;
}
int width = atoi(s.substr(pos+1).c_str());
uint8_t width = (uint8_t) strtol(s.substr(pos+1).c_str(), &end, 10);
string addr = s.substr(0, pos);
if ( CheckNumberError(s, end) )
return 0;
val->val.subnet_val.prefix = StringToAddr(addr);
val->val.subnet_val.length = width;
break;
@ -490,7 +533,7 @@ bool Ascii::DoUpdate()
Value* val = EntryToVal(stringfields[(*fit).position], *fit);
if ( val == 0 )
{
Error("Could not convert String value to Val");
Error(Fmt("Could not convert line '%s' to Val. Aborting file read.", line.c_str()));
return false;
}

View file

@ -48,6 +48,7 @@ private:
bool ReadHeader(bool useCached);
bool GetLine(string& str);
threading::Value* EntryToVal(string s, FieldMapping type);
bool CheckNumberError(const string & s, const char * end);
ifstream* file;
time_t mtime;

View file

@ -1,3 +1,4 @@
{
[9223372036854775800] = [c=18446744073709551612]
[9223372036854775800] = [c=18446744073709551612],
[-9223372036854775800] = [c=18446744073709551612]
}

View file

@ -0,0 +1,8 @@
error: ../input.log/Input::READER_ASCII: Number '12129223372036854775800' out of supported range. Number was truncated
error: ../input.log/Input::READER_ASCII: Number '121218446744073709551612' out of supported range. Number was truncated
error: ../input.log/Input::READER_ASCII: Number '9223372036854775801TEXTHERE' contained non-numeric trailing characters. Ignored trailing characters 'TEXTHERE'
error: ../input.log/Input::READER_ASCII: Number '1Justtext' contained non-numeric trailing characters. Ignored trailing characters 'Justtext'
error: ../input2.log/Input::READER_ASCII: String 'Justtext' contained no parseable number
error: ../input2.log/Input::READER_ASCII: Could not convert line 'Justtext 1' to Val. Aborting file read.
received termination signal
>>>

View file

@ -0,0 +1,5 @@
{
[9223372036854775807] = [c=18446744073709551615],
[9223372036854775800] = [c=4],
[9223372036854775801] = [c=1]
}

View file

@ -10,6 +10,7 @@
#fields i c
#types int count
9223372036854775800 18446744073709551612
-9223372036854775800 18446744073709551612
@TEST-END-FILE
@load frameworks/communication/listen

View file

@ -0,0 +1,55 @@
# (uses listen.bro just to ensure input sources are more reliably fully-read).
# @TEST-SERIALIZE: comm
#
# @TEST-EXEC: btest-bg-run bro bro -b %INPUT
# @TEST-EXEC: btest-bg-wait -k 5
# @TEST-EXEC: btest-diff out
# @TEST-EXEC: sed 1d .stderr > .stderrwithoutfirstline
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff .stderrwithoutfirstline
@TEST-START-FILE input.log
#separator \x09
#fields i c
#types int count
12129223372036854775800 121218446744073709551612
9223372036854775801TEXTHERE 1Justtext
9223372036854775800 -18446744073709551612
@TEST-END-FILE
@TEST-START-FILE input2.log
#separator \x09
#fields i c
#types int count
Justtext 1
@TEST-END-FILE
@load frameworks/communication/listen
global outfile: file;
module A;
type Idx: record {
i: int;
};
type Val: record {
c: count;
};
global servers: table[int] of Val = table();
event bro_init()
{
outfile = open("../out");
# first read in the old stuff into the table...
Input::add_table([$source="../input.log", $name="ssh", $idx=Idx, $val=Val, $destination=servers]);
Input::remove("ssh");
}
event Input::update_finished(name: string, source:string)
{
print outfile, servers;
Input::add_table([$source="../input2.log", $name="ssh2", $idx=Idx, $val=Val, $destination=servers]);
}