Fix memory leak in vector slice assignment

Two parts to this:

  * Only allow vector slice assignment in statement contexts, not in
    arbitrary assignment expressions.  E.g. it's not clear what the
    resulting value of `(v[1:2] = vector(1))` is for further expression
    chaining.  For reference, Python doesn't allow it either.

  * Add a subclass of AssignExpr to specialize the behavior for index
    slice assignments (because its behavior regarding expression
    chaining is different per the previous point) and Unref the RHS
    of things like `v[1:2] = vector(1)` after IndexExpr::Assign is
    finished inserting it (since no one else takes ownership of it).

Instead of using an Expr subclass, IndexSliceAssignExpr, we could
use a proper Stmt, since that's the only context we currently use it
for, but if we did ever to decide on allowing its use in arbitrary
expression contexts, then I expect we'll need it this way anyway
(just with a different IndexSliceAssignExpr::Eval implementation).
This commit is contained in:
Jon Siwek 2019-06-18 17:42:06 -07:00
parent 91835752b7
commit 385f500497
5 changed files with 140 additions and 21 deletions

View file

@ -49,7 +49,8 @@ typedef enum {
EXPR_FLATTEN,
EXPR_CAST,
EXPR_IS,
#define NUM_EXPRS (int(EXPR_IS) + 1)
EXPR_INDEX_SLICE_ASSIGN,
#define NUM_EXPRS (int(EXPR_INDEX_SLICE_ASSIGN) + 1)
} BroExprTag;
extern const char* expr_name(BroExprTag t);
@ -58,6 +59,7 @@ class Stmt;
class Frame;
class ListExpr;
class NameExpr;
class IndexExpr;
class AssignExpr;
class CallExpr;
class EventExpr;
@ -187,6 +189,18 @@ public:
return (AssignExpr*) this;
}
const IndexExpr* AsIndexExpr() const
{
CHECK_TAG(tag, EXPR_INDEX, "ExprVal::AsIndexExpr", expr_name)
return (const IndexExpr*) this;
}
IndexExpr* AsIndexExpr()
{
CHECK_TAG(tag, EXPR_INDEX, "ExprVal::AsIndexExpr", expr_name)
return (IndexExpr*) this;
}
void Describe(ODesc* d) const override;
bool Serialize(SerialInfo* info) const;
@ -663,6 +677,18 @@ protected:
Val* val; // optional
};
class IndexSliceAssignExpr : public AssignExpr {
public:
IndexSliceAssignExpr(Expr* op1, Expr* op2, int is_init);
Val* Eval(Frame* f) const override;
protected:
friend class Expr;
IndexSliceAssignExpr() {}
DECLARE_SERIAL(IndexSliceAssignExpr);
};
class IndexExpr : public BinaryExpr {
public:
IndexExpr(Expr* op1, ListExpr* op2, bool is_slice = false);
@ -682,6 +708,8 @@ public:
TraversalCode Traverse(TraversalCallback* cb) const override;
bool IsSlice() const { return is_slice; }
protected:
friend class Expr;
IndexExpr() { }
@ -691,6 +719,8 @@ protected:
void ExprDescribe(ODesc* d) const override;
DECLARE_SERIAL(IndexExpr);
bool is_slice;
};
class FieldExpr : public UnaryExpr {