@@ -284,11 +284,20 @@ private TranslatedValue translateList(CelExpr celExpr, CelAbstractSyntaxTree ast
284284 // check to a trivial identity check (e.g., `list_ref_0 == list_ref_0`).
285285 if (listRef == null ) {
286286 SeqExpr seq = ctx .mkEmptySeq (ctx .mkSeqSort (typeSystem .celValueSort ()));
287- for (CelExpr element : createList .elements ()) {
287+ ImmutableList <Integer > optionalIndices = createList .optionalIndices ();
288+ for (int i = 0 ; i < createList .elements ().size (); i ++) {
289+ CelExpr element = createList .elements ().get (i );
288290 TranslatedValue elem = translateExpr (element , ast );
289291 elementsTv .add (elem );
290292
291- seq = typeSystem .mkConcatSafe (seq , ctx .mkUnit (elem .z3Expr ()));
293+ if (optionalIndices .contains (i )) {
294+ Expr <?> optRef = typeSystem .getOptionalRef (elem .z3Expr ());
295+ BoolExpr hasVal = typeSystem .optHasValue (optRef );
296+ Expr <?> val = typeSystem .getOptionalValue (optRef );
297+ seq = (SeqExpr ) ctx .mkITE (hasVal , typeSystem .mkConcatSafe (seq , ctx .mkUnit (val )), seq );
298+ } else {
299+ seq = typeSystem .mkConcatSafe (seq , ctx .mkUnit (elem .z3Expr ()));
300+ }
292301 }
293302 listRef = typeSystem .mkListRefConst (LIST_REF_PREFIX );
294303 typeConstraints .add (ctx .mkEq (typeSystem .getSeq (listRef ), seq ));
@@ -297,7 +306,9 @@ private TranslatedValue translateList(CelExpr celExpr, CelAbstractSyntaxTree ast
297306 }
298307
299308 Expr <?> result = typeSystem .wrapList (listRef );
300- return TranslatedValue .propagateStrict (ctx , typeSystem , result , celExpr , elementsTv );
309+ BoolExpr baseTaint = ctx .mkFalse ();
310+ return TranslatedValue .propagateStrict (
311+ ctx , typeSystem , result , Optional .of (celExpr ), baseTaint , elementsTv );
301312 }
302313
303314 private TranslatedValue translateMap (CelExpr celExpr , CelAbstractSyntaxTree ast ) {
@@ -319,19 +330,37 @@ private TranslatedValue translateMap(CelExpr celExpr, CelAbstractSyntaxTree ast)
319330 elementsTv .add (valueTv );
320331
321332 BoolExpr keyAlreadyPresent = (BoolExpr ) ctx .mkSelect (mapPresence , key );
322- keysSeq =
323- ctx .mkITE (keyAlreadyPresent , keysSeq , typeSystem .mkConcatSafe (keysSeq , ctx .mkUnit (key )));
324-
325- mapValues = ctx .mkStore (mapValues , key , value );
326- mapPresence = ctx .mkStore (mapPresence , key , ctx .mkTrue ());
333+ if (entryAst .optionalEntry ()) {
334+ Expr <?> optRef = typeSystem .getOptionalRef (value );
335+ BoolExpr hasVal = typeSystem .optHasValue (optRef );
336+ Expr <?> optVal = typeSystem .getOptionalValue (optRef );
337+
338+ keysSeq =
339+ ctx .mkITE (
340+ hasVal ,
341+ ctx .mkITE (
342+ keyAlreadyPresent , keysSeq , typeSystem .mkConcatSafe (keysSeq , ctx .mkUnit (key ))),
343+ keysSeq );
344+ mapValues = (ArrayExpr ) ctx .mkITE (hasVal , ctx .mkStore (mapValues , key , optVal ), mapValues );
345+ mapPresence =
346+ (ArrayExpr ) ctx .mkITE (hasVal , ctx .mkStore (mapPresence , key , ctx .mkTrue ()), mapPresence );
347+ } else {
348+ keysSeq =
349+ ctx .mkITE (
350+ keyAlreadyPresent , keysSeq , typeSystem .mkConcatSafe (keysSeq , ctx .mkUnit (key )));
351+ mapValues = ctx .mkStore (mapValues , key , value );
352+ mapPresence = ctx .mkStore (mapPresence , key , ctx .mkTrue ());
353+ }
327354 }
328355
329356 typeConstraints .add (ctx .mkEq (typeSystem .getMapValues (mapRef ), mapValues ));
330357 typeConstraints .add (ctx .mkEq (typeSystem .getMapPresence (mapRef ), mapPresence ));
331358 typeConstraints .add (ctx .mkEq (typeSystem .getMapKeys (mapRef ), keysSeq ));
332359
333360 Expr <?> result = typeSystem .wrapMap (mapRef );
334- return TranslatedValue .propagateStrict (ctx , typeSystem , result , celExpr , elementsTv );
361+ BoolExpr baseTaint = ctx .mkFalse ();
362+ return TranslatedValue .propagateStrict (
363+ ctx , typeSystem , result , Optional .of (celExpr ), baseTaint , elementsTv );
335364 }
336365
337366 private TranslatedValue translateStruct (CelExpr celExpr , CelAbstractSyntaxTree ast ) {
@@ -379,15 +408,29 @@ private TranslatedValue translateStruct(CelExpr celExpr, CelAbstractSyntaxTree a
379408 // (`msg1 == msg2`) to work without using quantifiers (which avoids MBQI loops).
380409 // Because proto3 singular primitives do not have field presence, we also skip setting
381410 // `msgPresence`.
411+ Expr <?> effectiveValue ;
412+ BoolExpr isPresent ;
413+ if (entryAst .optionalEntry ()) {
414+ Expr <?> optRef = typeSystem .getOptionalRef (value );
415+ isPresent = typeSystem .optHasValue (optRef );
416+ effectiveValue = typeSystem .getOptionalValue (optRef );
417+ } else {
418+ isPresent = ctx .mkTrue ();
419+ effectiveValue = value ;
420+ }
421+
382422 BoolExpr shouldBypass =
383- fieldType .kind ().isPrimitive () ? ctx .mkEq (value , defaultVal ) : ctx .mkFalse ();
423+ fieldType .kind ().isPrimitive () ? ctx .mkEq (effectiveValue , defaultVal ) : ctx .mkFalse ();
424+
425+ BoolExpr shouldStore = ctx .mkAnd (isPresent , ctx .mkNot (shouldBypass ));
384426
385427 msgValues =
386- (ArrayExpr ) ctx .mkITE (shouldBypass , msgValues , ctx .mkStore (msgValues , key , value ));
428+ (ArrayExpr )
429+ ctx .mkITE (shouldStore , ctx .mkStore (msgValues , key , effectiveValue ), msgValues );
387430
388431 msgPresence =
389432 (ArrayExpr )
390- ctx .mkITE (shouldBypass , msgPresence , ctx .mkStore (msgPresence , key , ctx .mkTrue ()));
433+ ctx .mkITE (shouldStore , ctx .mkStore (msgPresence , key , ctx .mkTrue ()), msgPresence );
391434 }
392435
393436 typeConstraints .add (
@@ -396,7 +439,9 @@ private TranslatedValue translateStruct(CelExpr celExpr, CelAbstractSyntaxTree a
396439 typeConstraints .add (ctx .mkEq (typeSystem .getMsgPresence (msgRef ), msgPresence ));
397440
398441 Expr <?> result = typeSystem .wrapMessage (msgRef );
399- return TranslatedValue .propagateStrict (ctx , typeSystem , result , celExpr , elementsTv );
442+ BoolExpr baseTaint = ctx .mkFalse ();
443+ return TranslatedValue .propagateStrict (
444+ ctx , typeSystem , result , Optional .of (celExpr ), baseTaint , elementsTv );
400445 }
401446
402447 private Expr <?> getDefaultValueForType (CelType type ) {
@@ -644,6 +689,12 @@ private <T> T withScope(String varName, TranslatedValue value, Supplier<T> actio
644689 private TranslatedValue translateComprehension (CelExpr celExpr , CelAbstractSyntaxTree ast ) {
645690 CelComprehension comp = celExpr .comprehension ();
646691 CelExpr iterRangeExpr = comp .iterRange ();
692+ if (iterRangeExpr .exprKind ().getKind () == ExprKind .Kind .IDENT ) {
693+ TranslatedValue boundTv = symbolTable .get (iterRangeExpr .ident ().name ());
694+ if (boundTv != null ) {
695+ iterRangeExpr = boundTv .celExpr ().orElse (iterRangeExpr );
696+ }
697+ }
647698 List <IterationElement > iterationElements = new ArrayList <>();
648699 List <BoolExpr > taints = new ArrayList <>();
649700 List <Expr <?>> allRangeElems = new ArrayList <>();
@@ -1243,6 +1294,7 @@ private Optional<Object> toCacheKey(CelExpr expr) {
12431294 }
12441295 builder .add (elemKey .get ());
12451296 }
1297+ builder .add (expr .list ().optionalIndices ());
12461298 return Optional .of (builder .build ());
12471299 default :
12481300 return Optional .empty ();
0 commit comments