Fix record coercion tolerance of optional fields.

There were cases where coercing a record value with an uninitialized
field could cause a null pointer dereference even though the field
can validly be unset since it has &optional.
This commit is contained in:
Jon Siwek 2013-10-23 11:37:23 -05:00
parent 34aece4ddd
commit 7e95755ce5
4 changed files with 60 additions and 4 deletions

18
NEWS
View file

@ -259,6 +259,24 @@ Changed Functionality
fatal error in /usr/local/bro/share/bro/policy/frameworks/software/vulnerable.bro, line 41: BroType::AsRecordType (table/record) (set[record { min:record { major:count; minor:count; minor2:count; minor3:count; addl:string; }; max:record { major:count; minor:count; minor2:count; minor3:count; addl:string; }; }]) fatal error in /usr/local/bro/share/bro/policy/frameworks/software/vulnerable.bro, line 41: BroType::AsRecordType (table/record) (set[record { min:record { major:count; minor:count; minor2:count; minor3:count; addl:string; }; max:record { major:count; minor:count; minor2:count; minor3:count; addl:string; }; }])
- The type of ``Software::vulnerable_versions`` changed to allow
more flexibility and range specifications. An example usage:
.. code:: bro
const java_1_6_vuln = Software::VulnerableVersionRange(
$max = Software::Version($major = 1, $minor = 6, $minor2 = 0, $minor3 = 44)
);
const java_1_7_vuln = Software::VulnerableVersionRange(
$min = Software::Version($major = 1, $minor = 7),
$max = Software::Version($major = 1, $minor = 7, $minor2 = 0, $minor3 = 20)
);
redef Software::vulnerable_versions += {
["Java"] = set(java_1_6_vuln, java_1_7_vuln)
};
- The interface to extracting content from application-layer protocols - The interface to extracting content from application-layer protocols
(including HTTP, SMTP, FTP) has changed significantly due to the (including HTTP, SMTP, FTP) has changed significantly due to the
introduction of the new file analysis framework (see above). introduction of the new file analysis framework (see above).

View file

@ -2720,16 +2720,22 @@ RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr, bool allow_orphan
break; break;
} }
Val* v = Lookup(i);
if ( ! v )
// Check for allowable optional fields is outside the loop, below.
continue;
if ( ar_t->FieldType(t_i)->Tag() == TYPE_RECORD if ( ar_t->FieldType(t_i)->Tag() == TYPE_RECORD
&& ! same_type(ar_t->FieldType(t_i), Lookup(i)->Type()) ) && ! same_type(ar_t->FieldType(t_i), v->Type()) )
{ {
Expr* rhs = new ConstExpr(Lookup(i)->Ref()); Expr* rhs = new ConstExpr(v->Ref());
Expr* e = new RecordCoerceExpr(rhs, ar_t->FieldType(t_i)->AsRecordType()); Expr* e = new RecordCoerceExpr(rhs, ar_t->FieldType(t_i)->AsRecordType());
ar->Assign(t_i, e->Eval(0)); ar->Assign(t_i, e->Eval(0));
continue; continue;
} }
ar->Assign(t_i, Lookup(i)->Ref()); ar->Assign(t_i, v->Ref());
} }
for ( i = 0; i < ar_t->NumFields(); ++i ) for ( i = 0; i < ar_t->NumFields(); ++i )

View file

@ -1,2 +1,9 @@
[min=<uninitialized>, max=2] [min=<uninitialized>, max=2]
[min=7, max=42] [min=7, max=42]
[aaa=1, bbb=test, ccc=<uninitialized>, ddd=default]
{
[Java] = {
[min=<uninitialized>, max=[major=1, minor=6, minor2=0, minor3=44, addl=<uninitialized>]],
[min=[major=1, minor=7, minor2=<uninitialized>, minor3=<uninitialized>, addl=<uninitialized>], max=[major=1, minor=7, minor2=0, minor3=20, addl=<uninitialized>]]
}
}

View file

@ -1,4 +1,4 @@
# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: bro -b frameworks/software/vulnerable %INPUT >out
# @TEST-EXEC: btest-diff out # @TEST-EXEC: btest-diff out
type MyRec: record { type MyRec: record {
@ -6,7 +6,32 @@ type MyRec: record {
max: count; max: count;
}; };
type Bar: record {
aaa: count;
bbb: string &optional;
ccc: string &optional;
ddd: string &default="default";
};
const java_1_6_vuln = Software::VulnerableVersionRange(
$max = Software::Version($major = 1, $minor = 6, $minor2 = 0, $minor3 = 44)
);
const java_1_7_vuln = Software::VulnerableVersionRange(
$min = Software::Version($major = 1, $minor = 7),
$max = Software::Version($major = 1, $minor = 7, $minor2 = 0, $minor3 = 20)
);
redef Software::vulnerable_versions += {
["Java"] = set(java_1_6_vuln, java_1_7_vuln)
};
local myrec: MyRec = MyRec($max=2); local myrec: MyRec = MyRec($max=2);
print myrec; print myrec;
myrec = MyRec($min=7, $max=42); myrec = MyRec($min=7, $max=42);
print myrec; print myrec;
local data = Bar($aaa=1, $bbb="test");
print data;
print Software::vulnerable_versions;