diff --git a/src/Expr.cc b/src/Expr.cc index b5ed7d600a..53933b073f 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -1360,7 +1360,10 @@ SizeExpr::SizeExpr(Expr* arg_op) : UnaryExpr(EXPR_SIZE, arg_op) if ( IsError() ) return; - SetType(base_type(TYPE_COUNT)); + if ( op->Type()->InternalType() == TYPE_INTERNAL_DOUBLE ) + SetType(op->Type()->Ref()); + else + SetType(base_type(TYPE_COUNT)); } Val* SizeExpr::Eval(Frame* f) const diff --git a/src/Val.cc b/src/Val.cc index 3475ab5dc7..d57cffa45b 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -425,7 +425,7 @@ Val* Val::SizeVal() const return val_mgr->GetCount(val.uint_val); case TYPE_INTERNAL_DOUBLE: - return new Val(fabs(val.double_val), TYPE_DOUBLE); + return new Val(fabs(val.double_val), type->Tag()); case TYPE_INTERNAL_OTHER: if ( type->Tag() == TYPE_FUNC ) diff --git a/src/parse.y b/src/parse.y index c74035a3b9..a9f8d4b260 100644 --- a/src/parse.y +++ b/src/parse.y @@ -728,7 +728,12 @@ expr: | '|' expr '|' %prec '(' { set_location(@1, @3); - $$ = new SizeExpr($2); + auto e = $2; + + if ( IsIntegral(e->Type()->Tag()) ) + e = new ArithCoerceExpr(e, TYPE_INT); + + $$ = new SizeExpr(e); } | expr TOK_AS type diff --git a/testing/btest/Baseline/language.interval/out b/testing/btest/Baseline/language.interval/out index ae9ed5d74e..77cc8fcfba 100644 --- a/testing/btest/Baseline/language.interval/out +++ b/testing/btest/Baseline/language.interval/out @@ -15,6 +15,7 @@ add different time units (PASS) subtract different time units (PASS) absolute value (PASS) absolute value (PASS) +absolute value (PASS) assignment operator (PASS) assignment operator (PASS) multiplication operator (PASS) diff --git a/testing/btest/Baseline/language.sizeof/output b/testing/btest/Baseline/language.sizeof/output index 43cb73f763..c91b64cb4a 100644 --- a/testing/btest/Baseline/language.sizeof/output +++ b/testing/btest/Baseline/language.sizeof/output @@ -2,6 +2,7 @@ IPv4 Address 1.2.3.4: 32 IPv6 Address ::1: 128 Boolean T: 1 Count 10: 10 +Expr: 4 Double -1.23: 1.230000 Enum ENUM3: 2 File 21.000000 diff --git a/testing/btest/language/interval.bro b/testing/btest/language/interval.bro index 660683f5ca..c567d0af02 100644 --- a/testing/btest/language/interval.bro +++ b/testing/btest/language/interval.bro @@ -70,8 +70,9 @@ event bro_init() test_case( "compare different time units", in13 >= in35 ); test_case( "add different time units", in13 + in14 == 4min ); test_case( "subtract different time units", in24 - in23 == 0sec ); - test_case( "absolute value", |in25| == 2.0*3600 ); - test_case( "absolute value", |in36| == 2.5*86400 ); + test_case( "absolute value", |in25| == 2hr ); + test_case( "absolute value", |in36| == 2.5day ); + test_case( "absolute value", |5sec - 9sec| == 4sec ); in34 += 2hr; test_case( "assignment operator", in34 == 122min ); in34 -= 2hr; diff --git a/testing/btest/language/sizeof.bro b/testing/btest/language/sizeof.bro index 4f5833aa30..396984780a 100644 --- a/testing/btest/language/sizeof.bro +++ b/testing/btest/language/sizeof.bro @@ -64,6 +64,10 @@ print fmt("Boolean %s: %d", b, |b|); # Size of count: identity. print fmt("Count %s: %d", c, |c|); +# Size of integral arithmetic expression should coerce to int before absolute +# value operation to help prevent common unsigned int overflow situations. +print fmt("Expr: %d", |5 - 9|); + # Size of double: returns absolute value. print fmt("Double %s: %f", d, |d|); diff --git a/testing/btest/language/time.bro b/testing/btest/language/time.bro index dd4b6336fe..3310c3a3f7 100644 --- a/testing/btest/language/time.bro +++ b/testing/btest/language/time.bro @@ -27,7 +27,7 @@ event bro_init() test_case( "inequality", t1 != t3 ); test_case( "equality", t1 == t4 ); test_case( "subtract time", t2 - t1 == 3sec); - test_case( "size operator", |t5| == 1234567890.0 ); + test_case( "size operator", |t5| == t5 ); }