profile
viewpoint
Di Wang stonebuddha Carnegie Mellon University Pittsburgh, PA https://www.cs.cmu.edu/~diw3/

ankushdas/Nomos 7

This repository contains an implementation of Nomos, a programming language for smart contracts based on resource-aware session types.

stonebuddha/eopl 7

Essentials of Programming Languages, with OCaml implementations & Coq proofs

stonebuddha/sml-llvm 6

SML/NJ and MLton bindings for LLVM

stonebuddha/uthread 4

User-Level Thread Library

stonebuddha/vscode-better-sml 3

Standard ML Support for Visual Studio Code

stonebuddha/tree-sitter-sml 2

Standard ML Support for Tree-sitter

stonebuddha/YAL 2

Yet Another Language

GrammaTech/soot 1

Soot - A Java optimization framework

push eventstonebuddha/sundries

Di Wang

commit sha 6dd67e1286ae835b1305db4e6dd84516571a6376

updated db

view details

push time in 21 hours

push eventstonebuddha/sundries

Di Wang

commit sha 4a1deaabed869673dd1aee8f0682be8f7ce78f22

updated db

view details

push time in a day

push eventstonebuddha/MIRAI

Herman Venter

commit sha d2a0647b6e2506427f8c1f040689097efbdadbc1

Stacked heap counters (#566)

view details

push time in a day

push eventstonebuddha/sundries

Di Wang

commit sha 8ec1da9332e850a38936bbeaed17dfcfeddc9162

updated db

view details

push time in a day

push eventstonebuddha/sundries

Di Wang

commit sha ba3f309e6c99a78a1846d4d27b7402ffabd6ce96

updated db

view details

push time in a day

push eventstonebuddha/MIRAI

Herman Venter

commit sha f1a53b9b4eed745e1053779238b4330d84d85d26

Support for intrinsic copy and non inlined standard library asserts. (#565)

view details

push time in a day

push eventstonebuddha/sundries

Di Wang

commit sha 851ddd6e6bd5719e69747d9b4ffad9d63bc20f02

updated db

view details

push time in 2 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha ee50b2bab40cc058267a630a10b5fed2baae7d2d

Remove unnecessary feature from annotations crate (#563)

view details

Herman Venter

commit sha 60b89bf207b18faa4c9bffcc83fd0506aa958b8c

Refine rather than simplify to reduce &*ptr to just ptr (#562)

view details

Herman Venter

commit sha d04f6ed8a57a85d608144f15e646c18243b3856e

Do not refine PathEnum::Result into a leaked local (#564)

view details

push time in 2 days

Pull request review commentfacebookexperimental/MIRAI

Refine rather than simplify to reduce &*ptr to just ptr

 impl<'block, 'analysis, 'compilation, 'tcx, E>                 ..             } if *selector.as_ref() == PathSelector::Deref => {                 // We are taking a reference to the result of a deref. This is a bit awkward.-                // The deref essentially does a copy of the value denoted by the qualifier.-                // If this value is structured and not heap allocated, the copy must be done-                // with copy_or_move_elements.+                // The deref, by itself, essentially does a copy of the value denoted by the qualifier.+                // When combined with an address_of operation, however, things are more complicated.+                // If the contents at offset 0 from the target of the pointer being dereferenced is+                // a fat (slice) pointer then the address_of operation results in a copy of the fat pointer.+                // We check for this by looking at the type of the operation result target.                 if type_visitor::is_slice_pointer(&target_type.kind)                     || self                         .bv                         .type_visitor                         .starts_with_slice_pointer(&target_type.kind)                 {-                    // Copying to a fat pointer without a cast, so the source pointer is fat too.-                    // qualifier, however, has been modified into a thin pointer because of the deref.-                    // Undo the damage by stripping off the field 0.+                    // If we get here we are effectively copying to a fat pointer without a cast,+                    // so there is no type information to use to come up with the length part of+                    // the fat pointer. This implies that the source value must itself be a fat+                    // pointer. This is, however, not what we'll see if we get the type of the+                    // qualifier path. The reason for that is the ambiguous semantics of the+                    // deref operator: Mostly, doing a deref of a fat pointer means doing a+                    // deref of the thin pointer since that is what we expect when de-referencing+                    // a pointer, whether it is fat or thin.+                    //+                    // When combined with an address_of operator, however, deref just means to+                    // copy the pointer, whether it is fat of thin. (In this case, it must be fat.)

whether it is fat of thin -> no matter that it is fat or thin

hermanventer

comment created time in 3 days

push eventstonebuddha/MIRAI

François Garillot

commit sha 8022f7619f8b01585cc0726134778b12e87de558

Make ./setup.sh more robust (#559) The current setup script runs under the context of the directory from which it is called. If that's the directory in which "./setup.sh" lives, it will pickup the right 'rust-toolchain'. Otherwise it won't. This fixes this fragility by fetching the rust-toolchain file contents and passing them as an explicit rustup argument.

view details

Herman Venter

commit sha 5bac73c228b48a3bc7550f9693f20a817550c71a

Update rustc version to latest nightly and adapt MIRAI. (#560)

view details

Herman Venter

commit sha 6070380bafaae08be13d4b2ffe0d265940a255e8

Add Function pointers to special case for thin pointers (#561)

view details

push time in 3 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 058afeec51322a95e2618c88173911bdd9d07dda

Fix attach_tag_to_elements

view details

push time in 7 days

push eventfacebookexperimental/MIRAI

Di Wang

commit sha 058afeec51322a95e2618c88173911bdd9d07dda

Fix attach_tag_to_elements

view details

push time in 7 days

PR merged facebookexperimental/MIRAI

Fix attach_tag_to_elements CLA Signed

Description

The method attach_tag_to_elements should use decomposed value paths (with respect to joins) as both the source and the target of strong/weak updates.

Type of change

  • [x] Bug fix (non-breaking change which fixes an issue)
  • [ ] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [ ] API change with a documentation update
  • [ ] Additional test coverage
  • [ ] Code cleanup or just keeping up with the latest Rustc nightly

How Has This Been Tested?

./validate.sh (MIRAI on MIRAI failed) ran MIRAI over Libra

+3 -5

0 comment

2 changed files

stonebuddha

pr closed time in 7 days

PR opened facebookexperimental/MIRAI

Fix attach_tag_to_elements

Description

The method attach_tag_to_elements should use decomposed value paths (with respect to joins) as both the source and the target of strong/weak updates.

Type of change

  • [x] Bug fix (non-breaking change which fixes an issue)
  • [ ] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [ ] API change with a documentation update
  • [ ] Additional test coverage
  • [ ] Code cleanup or just keeping up with the latest Rustc nightly

How Has This Been Tested?

./validate.sh (MIRAI on MIRAI failed) ran MIRAI over Libra

+3 -5

0 comment

2 changed files

pr created time in 7 days

push eventstonebuddha/MIRAI

Di Wang

commit sha b0406921c41e8224232064d70a451313d06e5bc5

Fix attach_tag_to_elements

view details

push time in 7 days

create barnchstonebuddha/MIRAI

branch : precise_path_for_tagging

created branch time in 7 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 1d60fef8d3313c439d32e93d4eba05089dee6a12

Make joined target paths into a pattern (#557)

view details

push time in 7 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 3cdefaf44aaed2c0c2a361963197d1f6f74bf37f

Adapt to new nightly rustc (#556)

view details

push time in 8 days

pull request commentfacebookexperimental/MIRAI

Adapt to new nightly rustc

I encountered the following error when running validate.sh:

RUSTFLAGS="-Z always_encode_mir" RUSTC_WRAPPER=mirai RUST_BACKTRACE=1 MIRAI_LOG=warn cargo build --lib -p mirai
...
Error: Sort mismatch at argument #1 for function (declare-fun < (Int Int) Bool) supplied sort is <null>

It seems to be caused by Z3.

hermanventer

comment created time in 8 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 60060f948592301a1eab30263a78d2d29226fc3b

Encode tag checks as SMT queries (#555)

view details

push time in 9 days

pull request commentfacebookexperimental/MIRAI

Encode tag checks as SMT queries

Updated Z3 version to 4.8.8.

stonebuddha

comment created time in 9 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 16ac34bbe2fbc5f51c83dae53c5e05e3e86b91b4

Encode tag checks as SMT queries

view details

push time in 9 days

pull request commentfacebookexperimental/MIRAI

Encode tag checks as SMT queries

Need to figure out CI test failures.

I reproduce the failure locally by using the z3 binary in the repo.

stonebuddha

comment created time in 9 days

pull request commentfacebookexperimental/MIRAI

Encode tag checks as SMT queries

The test failures are hard to make out. It seems like Z3 is crashing. Does this work on your local machine?

Yes, it works normally on my machine.

stonebuddha

comment created time in 9 days

PR opened facebookexperimental/MIRAI

Encode tag checks as SMT queries

Description

This commit implements Z3 encoding for tag checks. To ensure that the expression domain is precise enough to reduce tag checks to SMT queries, UnknownTagCheck expressions now record values instead of paths. On the Z3 side, I declare a top-level logical predicate has_tag in a way that has_tag(path, tag) encodes an uninterpreted Boolean-valued function call that checks whether path is attached with tag or not. When MIRAI generates a Z3 AST for UnknownTagCheck { operand, tag, .. }, it invokes the general_has_tag(operand, tag) routine, which recursively synthesizes a tag-check query from sub-expressions. This routine works similar to AbstractValue::get_tags.

This commit also includes several tests that indicate bugs or loss of precision. One is that when we tag a function parameter that is a struct, we don't know paths rooted at it so we don't tag its fields. The other is that the current methodology for copy_or_move_elements and attach_tag_to_elements only tries to split a path after enumerating paths rooted at the target path, so updating if ... { local1 } else { local2 } would not update local1.field or local2.field.

Type of change

  • [ ] Bug fix (non-breaking change which fixes an issue)
  • [x] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [ ] API change with a documentation update
  • [ ] Additional test coverage
  • [ ] Code cleanup or just keeping up with the latest Rustc nightly

How Has This Been Tested?

./validate.sh ran MIRAI over Libra

+424 -182

0 comment

10 changed files

pr created time in 9 days

push eventstonebuddha/MIRAI

Di Wang

commit sha dd506461b00dc2b720895185eb66f641f98e74c8

Encode tag checks as SMT queries

view details

push time in 9 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 0e6352a9c73f59272612a83f96bfc8b3e71fa088

Cleanup non_patterned_copy_or_move_elements (#554)

view details

Di Wang

commit sha f6c18ab9f08f9b197e645e0d0842e1d7995cd6f1

Encode tag checks as SMT queries

view details

push time in 9 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 0e6352a9c73f59272612a83f96bfc8b3e71fa088

Cleanup non_patterned_copy_or_move_elements (#554)

view details

push time in 9 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 7a8bdefc94dbe4f8c7f2bfe54ca444ba0960c749

Encode tag checks as SMT queries

view details

push time in 9 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 0427676376a45c7f18b55e21ff171082702bcc63

Encode tag checks as SMT queries

view details

push time in 9 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 22e930d464d3dc96f9283f6339ae532138c28466

Encode tag checks as SMT queries

view details

push time in 9 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 9eda954f63d27b3065821237a46930bbdf8b2a10

Encode tag checks as SMT queries

view details

push time in 9 days

create barnchstonebuddha/MIRAI

branch : tag_check_as_smt

created branch time in 9 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 8e49a50ae27f43854a07b11eaafd96616f6ce1a9

Implement weak updates for tags

view details

push time in 10 days

push eventfacebookexperimental/MIRAI

Di Wang

commit sha 8e49a50ae27f43854a07b11eaafd96616f6ce1a9

Implement weak updates for tags

view details

push time in 10 days

PR merged facebookexperimental/MIRAI

Implement weak updates for tags CLA Signed

Description

This commit implements weak updates for adding tags. For example, when tagging an indexed path a[i] where i is unknown, we need to update all indexed paths rooted at a in a way that they may be tagged.

This commit is not in a good shape yet because there are some issues, but I think it would be convenient to have code around during a discussion. The first issue is that the logic of attach_tag_to_elements is very similar to that of copy_or_move_elements, and there are many duplicate code segments (for example, the treatment of index patterns). It is possible to unify the two routines by adding a parameter to copy_or_move_elements to indicate some extra operations right before we move/copy an element. I propose to implement a general routine like copy_or_move_elements_with_op in a way that both copy_or_move_elements and attach_tag_to_elements can invoke it.

The other issue is the logic for copy_or_move_elements. Currently, it handles patterns and then invokes Environment::update_value_at, which can split a path that was constructed via join. However, it seems that we need to split the path first, because the target path might be a join of multiple indexed paths.

Type of change

  • [ ] Bug fix (non-breaking change which fixes an issue)
  • [x] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [ ] API change with a documentation update
  • [ ] Additional test coverage
  • [ ] Code cleanup or just keeping up with the latest Rustc nightly

How Has This Been Tested?

./validate.sh ran MIRAI over Libra

+171 -64

0 comment

5 changed files

stonebuddha

pr closed time in 10 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 9c5270efc6bc80bb96a44e7016a5002076c64f08

Implement weak updates for tags

view details

push time in 10 days

PR closed facebookexperimental/MIRAI

Reviewers
Keep track of tag checks from preconditions CLA Signed

Description

The commit improves the precision of tag checks by refining tag abstractions when refining an abstract value with respect to a path condition. For example, if the path condition assumes (e.g., by preconditions) has_tag!(param, Secret) where param is a parameter, we want to update the abstract value of param to reflect that it has tag Secret. The information is needed to propagate tag Secret precisely when param is used in a compound expression later in the function.

Type of change

  • [ ] Bug fix (non-breaking change which fixes an issue)
  • [x] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [ ] API change with a documentation update
  • [ ] Additional test coverage
  • [ ] Code cleanup or just keeping up with the latest Rustc nightly

How Has This Been Tested?

./validate.sh ran MIRAI over Libra

+57 -7

2 comments

3 changed files

stonebuddha

pr closed time in 10 days

pull request commentfacebookexperimental/MIRAI

Keep track of tag checks from preconditions

I'm going to close this PR but investigate this issue later after implementing SMT-based tag tracking.

stonebuddha

comment created time in 10 days

push eventstonebuddha/MIRAI

Di Wang

commit sha d592746325484352de0073dd48b8e92aa39919bd

Implement weak updates for tags

view details

push time in 10 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 6ffa33d20316645999b9dfba22cccbdf7325987f

Factor out target pattern expansion (#553)

view details

Di Wang

commit sha 4c8e5259877810c5ecdb0c3b3955f0ce5c5616f2

Implement weak updates for tags

view details

push time in 10 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 6ffa33d20316645999b9dfba22cccbdf7325987f

Factor out target pattern expansion (#553)

view details

push time in 10 days

push eventstonebuddha/MIRAI

Di Wang

commit sha d5fe2fe3069a65bbeb5cac687729a88fb79bae1e

Keep track of tag checks from preconditions

view details

push time in 10 days

Pull request review commentfacebookexperimental/MIRAI

Factor out target pattern expansion

 impl<'analysis, 'compilation, 'tcx, E> BodyVisitor<'analysis, 'compilation, 'tcx         // a collection of values obtained from the qualifier. We need to copy/move those         // individually, hence we use a helper to call copy_or_move_elements recursively on         // each source_path expansion.-        let expanded_source_pattern = self.expanded_source_pattern(+        let expanded_source_pattern = self.try_expand_source_pattern(             &target_path,             &source_path,-            |_self, target_path, expanded_path| {-                _self.copy_or_move_elements(-                    target_path,-                    expanded_path,-                    root_rustc_type,-                    move_elements,-                )+            root_rustc_type,+            |_self, target_path, expanded_path, ty| {+                _self.copy_or_move_elements(target_path, expanded_path, ty, move_elements)             },         );         if expanded_source_pattern {             return;         }          // Get here if source_path is not a pattern. Now see if target_path is a pattern.--        // Some target paths are wild card patterns and need to be dealt with via weak updates-        if let PathEnum::QualifiedPath {-            ref qualifier,-            ref selector,-            ..-        } = &target_path.value-        {-            match &**selector {-                PathSelector::Index(value) => {-                    if let Expression::CompileTimeConstant(..) = &value.expression {-                        // fall through, the target path is unique-                    } else {-                        self.weak_updates(qualifier, &source_path, |v| value.equals(v));-                        // and now fall through for a strong update of target_path-                    }-                }-                PathSelector::Slice(count) => {-                    // if the count is known at this point, expand it like a pattern.-                    if let Expression::CompileTimeConstant(ConstantDomain::U128(val)) =-                        &count.expression-                    {-                        self.expand_slice(-                            &qualifier,-                            &source_path,-                            0,-                            *val as u32,-                            |_self, target_path, source_path| {-                                _self.copy_or_move_elements(-                                    target_path,-                                    source_path,-                                    root_rustc_type,-                                    move_elements,-                                )-                            },-                        );-                    } else {-                        // Any that that might get assigned to by this slice need to get weakened.-                        // That is, the value has to become a condition based on index < count.-                        self.weaken_paths_that_index(qualifier, count);-                    }-                    // fall through-                }-                _ => {-                    // fall through-                }-            }-        }--        // Assigning to a fixed length array is like a pattern-        if let TyKind::Array(ty, len) = &root_rustc_type.kind {-            let param_env = self.type_visitor.get_param_env();-            let len = len-                .try_eval_usize(self.tcx, param_env)-                .expect("Array to have constant len");--            self.expand_slice(-                &target_path,-                &source_path,-                0,-                len as u32,-                |_self, target_path, source_path| {-                    _self.copy_or_move_elements(target_path, source_path, ty, move_elements)-                },-            );+        // If the pattern is a known size, copy_of_move_elements is called recursively+        // on each expansion of the target pattern and try_expand_target_pattern returns true.+        // If not, all of the paths that might match the pattern are weakly updated to account+        // for the possibility that this assignment might update them (or not).+        let expanded_target_pattern = self.try_expand_target_pattern(+            &target_path,+            &source_path,+            root_rustc_type,+            |_self, target_path, source_path, root_rustc_type| {

The name root_rustc_type here might be a bit misleading. Maybe elem_rustc_type?

hermanventer

comment created time in 11 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 679ecadbbc362329515356b95705d6b1f03fff21

Factor out pattern expansion (#551)

view details

Di Wang

commit sha ac2cdff9d6497f96ca68087539025bc09c265b3a

Implement weak updates for tags

view details

push time in 13 days

Pull request review commentfacebookexperimental/MIRAI

Implement weak updates for tags

 const SECRET_SANITIZER: TagPropagationSet = tag_propagation_set!(TagPropagation:  type SecretSanitizer = SecretSanitizerKind<SECRET_SANITIZER>; -pub fn test() {-    let secret = 23333;+pub fn test(secret: i32) {+    precondition!(does_not_have_tag!(&secret, SecretTaint));+    precondition!(does_not_have_tag!(&secret, SecretSanitizer));      add_tag!(&secret, SecretTaint);     verify!(has_tag!(&secret, SecretTaint));     verify!(does_not_have_tag!(&secret, SecretSanitizer));      let info = secret | 1;     verify!(has_tag!(&info, SecretTaint));-    verify!(does_not_have_tag!(&info, SecretSanitizer));+    verify!(does_not_have_tag!(&info, SecretSanitizer)); //~ possible false verification condition

Submitted another PR #552 for this issue.

stonebuddha

comment created time in 13 days

PR opened facebookexperimental/MIRAI

Keep track of tag checks from preconditions

Description

The commit improves the precision of tag checks by refining tag abstractions in an environment using the environment's entry condition. For example, if a function has a precondition that assumes has_tag!(param, Secret) where param is a parameter, we want to update the abstract value of param to reflect that it has tag Secret. The information is needed to propagate tag Secret precisely when param is used in a compound expression later in the function.

Type of change

  • [ ] Bug fix (non-breaking change which fixes an issue)
  • [x] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [ ] API change with a documentation update
  • [ ] Additional test coverage
  • [ ] Code cleanup or just keeping up with the latest Rustc nightly

How Has This Been Tested?

./validate.sh ran MIRAI over Libra

+63 -6

0 comment

5 changed files

pr created time in 13 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 679ecadbbc362329515356b95705d6b1f03fff21

Factor out pattern expansion (#551)

view details

Di Wang

commit sha 764de77469dfb93947be56645133d53d70acee22

Keep track of tag checks from preconditions

view details

push time in 13 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 679ecadbbc362329515356b95705d6b1f03fff21

Factor out pattern expansion (#551)

view details

push time in 13 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 27d9db52c7b36f842e6485b30e426dbc93d9c0e9

Keep track of tag checks from preconditions

view details

push time in 13 days

create barnchstonebuddha/MIRAI

branch : tag_preconditions

created branch time in 13 days

Pull request review commentfacebookexperimental/MIRAI

Implement weak updates for tags

 const SECRET_SANITIZER: TagPropagationSet = tag_propagation_set!(TagPropagation:  type SecretSanitizer = SecretSanitizerKind<SECRET_SANITIZER>; -pub fn test() {-    let secret = 23333;+pub fn test(secret: i32) {+    precondition!(does_not_have_tag!(&secret, SecretTaint));+    precondition!(does_not_have_tag!(&secret, SecretSanitizer));      add_tag!(&secret, SecretTaint);     verify!(has_tag!(&secret, SecretTaint));     verify!(does_not_have_tag!(&secret, SecretSanitizer));      let info = secret | 1;     verify!(has_tag!(&info, SecretTaint));-    verify!(does_not_have_tag!(&info, SecretSanitizer));+    verify!(does_not_have_tag!(&info, SecretSanitizer)); //~ possible false verification condition

It's not really the expected behavior. It's caused by the over-approximation of the get_tags function. In this case, we we would like get_tags to return a tag domain element that maps SecretSanitizer to UnknownTagCheck(secret, SecretSanitizer) instead of Top. I should have added a todo comment for this.

stonebuddha

comment created time in 14 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 5b78f8d7973f619e4307f7f26b5b35890b0a374a

Fix copy_from_slice. (#549) * Fix copy_from_slice. * Update body_visitor.rs

view details

Di Wang

commit sha 5bf553ee8d2c190e332e2ff2c13f11b8d3253489

Implement weak updates for tags

view details

push time in 14 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 5b78f8d7973f619e4307f7f26b5b35890b0a374a

Fix copy_from_slice. (#549) * Fix copy_from_slice. * Update body_visitor.rs

view details

push time in 14 days

PR opened facebookexperimental/MIRAI

Implement weak updates for tags

Description

This commit implements weak updates for adding tags. For example, when tagging an indexed path a[i] where i is unknown, we need to update all indexed paths rooted at a in a way that they may be tagged.

This commit is not in a good shape yet because there are some issues, and I think it would be convenient to have code around during a discussion. The first issue is that the logic of attach_tag_to_elements is very similar to that of copy_or_move_elements, and there are many duplicate code segments (for example, the treatment of index patterns). It is possible to unify the two routines by adding a parameter to copy_or_move_elements to indicate some extra operations right before we move/copy an element.

The other issue is the logic for copy_or_move_elements. Currently, it handles patterns and then invokes Environment::update_value_at, which can split a path that was constructed via join. However, it seems that we need to split the path first, because the target path might be a join of multiple indexed paths.

Type of change

  • [ ] Bug fix (non-breaking change which fixes an issue)
  • [x] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [ ] API change with a documentation update
  • [ ] Additional test coverage
  • [ ] Code cleanup or just keeping up with the latest Rustc nightly

How Has This Been Tested?

./validate.sh ran MIRAI over Libra

+235 -63

0 comment

5 changed files

pr created time in 14 days

push eventstonebuddha/MIRAI

Di Wang

commit sha c63de4d9c9554b0614a4218164423fea239e1888

Implement weak updates for tags

view details

push time in 14 days

push eventstonebuddha/MIRAI

Di Wang

commit sha fa55e0cfee796398fd06ac184b1a42916534f0ed

Implement weak updates for tags

view details

push time in 14 days

Pull request review commentfacebookexperimental/MIRAI

Fix copy_from_slice.

 impl<'analysis, 'compilation, 'tcx, E> BodyVisitor<'analysis, 'compilation, 'tcx                     }                 }                 Expression::Reference(path) => {-                    let target_type = self+                    let deref_type = self                         .type_visitor                         .get_path_rustc_type(&tpath, self.current_span);                     if self                         .type_visitor-                        .starts_with_slice_pointer(&target_type.kind)+                        .starts_with_slice_pointer(&deref_type.kind)                     {+                        if let PathEnum::QualifiedPath { selector, .. } = &tpath.value {+                            if matches!(selector.as_ref(), PathSelector::Field(0)) {+                                // rpath = qualifier.0 and rvalue = &path, so thin pointer copy

rpath -> tpath

hermanventer

comment created time in 14 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha d15ad2860ae7a3308710653eb56cf6cb7d0907e8

Really defer refinement. (#548)

view details

Di Wang

commit sha bba2a94ddb620246b46ceac9e015389234599359

Implement weak updates for tags

view details

push time in 14 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha d15ad2860ae7a3308710653eb56cf6cb7d0907e8

Really defer refinement. (#548)

view details

push time in 14 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 6926d1c9a1b4f8145aa981d49e3d80f13e0895b5

Implement weak updates for tags

view details

push time in 14 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 06770f88facf6874b8ee8d8253c0539d34c7f539

Implement weak updates for tags

view details

push time in 14 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 10d7067d8addd57ae2e5cef98d6c549514c71d11

Specialize types of operands that are closures (#544)

view details

Herman Venter

commit sha 3a8d68299dc6a95e19c475f1ca8ef9589cde7ccb

Tweak readable version of an impl method summary key string (#545)

view details

Herman Venter

commit sha a1c249bc851e07a58a7164f7ee0fcf97461a42fd

Get function references from function types. (#547)

view details

Di Wang

commit sha 8959390eab59217efb74c27dae15a7be665bb3c4

Add an expression kind for unknown tag checks

view details

Di Wang

commit sha 39aa1001bccf689d60f7756e7848878d1cb1f960

Implement weak updates for tags

view details

push time in 14 days

push eventstonebuddha/MIRAI

Di Wang

commit sha a346eb8c7b397981c98c649c5c07e0a28fdbba41

implementing weak updates for tags

view details

push time in 15 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 8959390eab59217efb74c27dae15a7be665bb3c4

Add an expression kind for unknown tag checks

view details

push time in 15 days

push eventfacebookexperimental/MIRAI

Di Wang

commit sha 8959390eab59217efb74c27dae15a7be665bb3c4

Add an expression kind for unknown tag checks

view details

push time in 15 days

PR merged facebookexperimental/MIRAI

Support unknown tag checks CLA Signed

Description

This commit introduces a new expression UnknownTagCheck to resolve tag queries on function parameters. The mechanism is similar to unknown model fields. When checking whether the value at a path is attached with a tag or not, if the path is not tracked by the current environment (e.g., it is rooted at a function parameter), we create an UnknownTagCheck to postpone the tag query until we get more information from the caller.

This commit also updates the documentation for the tag domain and renames several tag-related APIs. The documentation for TagDomain now has a more detailed explanation of the design choices, and the names of tag-related APIs are more consistent with their intended usage.

Other changes in this commits are mostly code cleanup for the tag adding/checking logic. Now MIRAI will raise an error on add_tag!/has_tag!/does_not_have_tag! macros if (i) the tag type is not a generic type whose first parameter is a constant of type TagPropagationSet, or (ii) the tagged value is a reference.

Type of change

  • [ ] Bug fix (non-breaking change which fixes an issue)
  • [x] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [ ] API change with a documentation update
  • [ ] Additional test coverage
  • [x] Code cleanup or just keeping up with the latest Rustc nightly

How Has This Been Tested?

./validate.sh ran MIRAI over Libra

+341 -152

0 comment

9 changed files

stonebuddha

pr closed time in 15 days

push eventstonebuddha/MIRAI

Di Wang

commit sha cbbd145cfe5eaa2dc8420cab6645036f3aed7246

Add an expression kind for unknown tag checks

view details

push time in 15 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha a1c249bc851e07a58a7164f7ee0fcf97461a42fd

Get function references from function types. (#547)

view details

Di Wang

commit sha 477da9994ef34fa2397877faf47e579bb6848811

Add an expression kind for unknown tag checks

view details

push time in 15 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha a1c249bc851e07a58a7164f7ee0fcf97461a42fd

Get function references from function types. (#547)

view details

push time in 15 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 0c9fc7cdb1ee866e267763327aa63b41ff2b30ab

Add an expression kind for unknown tag checks

view details

push time in 15 days

Pull request review commentfacebookexperimental/MIRAI

Support unknown tag checks

 impl<'call, 'block, 'analysis, 'compilation, 'tcx, E>                 match rustc_gen_args[1].unpack() {                     GenericArgKind::Type(rustc_type) => tag_rustc_type = rustc_type,                     _ => {-                        assume_unreachable!("expected the second generic argument of tag-related function calls to be a type");+                        assume_unreachable!(

These assumptions are documented by this function's documentation and also a comment on line 2117. This is ensured by the rust type checker: the second argument of add_tag!/has_tag! macros must be a type.

stonebuddha

comment created time in 15 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 3a8d68299dc6a95e19c475f1ca8ef9589cde7ccb

Tweak readable version of an impl method summary key string (#545)

view details

Di Wang

commit sha adbb6486badbddc58c0efa9b75888f65e42ed15c

Add an expression kind for unknown tag checks

view details

push time in 15 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 3a8d68299dc6a95e19c475f1ca8ef9589cde7ccb

Tweak readable version of an impl method summary key string (#545)

view details

push time in 15 days

PR opened facebookexperimental/MIRAI

Support unknown tag checks

Description

This commit introduces a new expression UnknownTagCheck to resolve tag queries on function parameters. The mechanism is similar to unknown model fields. When checking whether the value at a path is attached with a tag or not, if the path is not tracked by the current environment (e.g., it is rooted at a function parameter), we create an UnknownTagCheck to postpone the tag query until we get more information from the caller.

This commit also updates the documentation for the tag domain and renames several tag-related APIs. The documentation for TagDomain now has a more detailed explanation of the design choices, and the names of tag-related APIs are more consistent with their intended usage.

Other changes in this commits are mostly code cleanup for the tag adding/checking logic. Now MIRAI will raise an error on add_tag!/has_tag!/does_not_have_tag! macros if (i) the tag type is not a generic type whose first parameter is a constant of type TagPropagationSet, or (ii) the tagged value is a reference.

Type of change

  • [ ] Bug fix (non-breaking change which fixes an issue)
  • [x] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [ ] API change with a documentation update
  • [ ] Additional test coverage
  • [x] Code cleanup or just keeping up with the latest Rustc nightly

How Has This Been Tested?

./validate.sh ran MIRAI over Libra

+342 -152

0 comment

9 changed files

pr created time in 15 days

push eventstonebuddha/MIRAI

Di Wang

commit sha e905ff9dd4a6fdc53500931e78b59e91473b9416

Add an expression kind for unknown tag checks

view details

push time in 15 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 9c6aee553291ea676c0df0f23baaaa6c663497f4

Add an expression kind for unknown tag checks

view details

push time in 15 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 10d7067d8addd57ae2e5cef98d6c549514c71d11

Specialize types of operands that are closures (#544)

view details

Di Wang

commit sha 3aea89bb5d5d3718012212a03b5c91cf36b2c8c8

Add an expression kind for unknown tag checks

view details

push time in 15 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 5bc22531d75096d529adecf4308feae529c15f8b

Add an expression kind for unknown tag checks

view details

push time in 16 days

push eventstonebuddha/MIRAI

Herman Venter

commit sha 10d7067d8addd57ae2e5cef98d6c549514c71d11

Specialize types of operands that are closures (#544)

view details

push time in 16 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 969d20225a06f6f91d2e4d5737b5aedb1b75bd8a

Add an expression kind for unknown tag checks

view details

Di Wang

commit sha d7fac768d64ebc773e17d14be92f7dc95849be42

implementing weak updates for tags

view details

push time in 16 days

push eventstonebuddha/MIRAI

Di Wang

commit sha 008c47973565b2ed36db364a03d0aba199504d1f

Add an expression kind for unknown tag checks

view details

push time in 16 days

PR closed facebookexperimental/MIRAI

Add an expression kind for unknown tag checks CLA Signed

Description

This commit introduces a new expression UnknownTagCheck to resolve tag queries on function parameters. The mechanism is similar to unknown model fields. When checking whether the value at a path is attached with a tag or not, if the path is not tracked by the current environment and is rooted at a parameter, we create an UnknownTagCheck to postpone the tag query until we get more information about the parameters from the caller.

Type of change

  • [ ] Bug fix (non-breaking change which fixes an issue)
  • [x] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [ ] API change with a documentation update
  • [ ] Additional test coverage
  • [ ] Code cleanup or just keeping up with the latest Rustc nightly

How Has This Been Tested?

./validate.sh ran MIRAI over Libra

+157 -62

1 comment

9 changed files

stonebuddha

pr closed time in 16 days

pull request commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

I'm going to close this PR and submit a new one after I make things more clear.

stonebuddha

comment created time in 16 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 impl AbstractValueTrait for Rc<AbstractValue> {             | Expression::HeapBlockLayout { .. }             | Expression::Reference { .. }

Well, this does not really make tag checks easier. If references propagate tags, then dereferences should also propagate them for the same reason. If this is the case, then we might need to check &&&&&...secret when we just want to check secret.

stonebuddha

comment created time in 16 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 impl AbstractValueTrait for Rc<AbstractValue> {             | Expression::HeapBlockLayout { .. }             | Expression::Reference { .. }

My assumption there was that heap addresses do not lack information. We can definitely make references propagate everything, which is safe and makes tag checks easier.

stonebuddha

comment created time in 16 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 impl AbstractValueTrait for Rc<AbstractValue> {                     default.clone()                 }             }+            Expression::UnknownTagCheck {+                path,+                tag,+                checking_presence,+            } => {+                if let Some(val) = environment.value_at(&path) {+                    let tag_presence = val.has_tag(tag);+                    if tag_presence.is_top() {+                        // Still unknown, fall through.

In this block there are two cases where we return UnknownTagCheck: either path is not in the environment, or tag_presence is top. Should we duplicate the creation of the UnknownTagCheck expression?

stonebuddha

comment created time in 16 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 impl AbstractValueTrait for Rc<AbstractValue> {             | Expression::HeapBlockLayout { .. }             | Expression::Reference { .. }

Similar to the issue on tag checks: can reference propagate tags?

stonebuddha

comment created time in 16 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 impl AbstractValueTrait for Rc<AbstractValue> {             | Expression::HeapBlockLayout { .. }             | Expression::Reference { .. }             | Expression::UnknownModelField { .. }-            | Expression::Variable { .. } => {-                return TagDomain::for_empty_set();+            | Expression::UnknownTagCheck { .. } => return TagDomain::empty_set(),

This depends on "whether a tag check can propagate other tags or not". What's your opinion here? Should we make this controllable via tag propagation set?

stonebuddha

comment created time in 16 days

push eventstonebuddha/MIRAI

Di Wang

commit sha d24f34a154132f9ce6727aa6c3f8dc8f4a37e720

Add an expression kind for unknown tag checks

view details

Di Wang

commit sha d1a308d966f12597b7d598726a7088bb530df375

implementing weak updates for tags

view details

push time in 17 days

push eventstonebuddha/MIRAI

Di Wang

commit sha d24f34a154132f9ce6727aa6c3f8dc8f4a37e720

Add an expression kind for unknown tag checks

view details

push time in 17 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 impl TagDomain {     pub fn add_tag(&self, tag: Tag, val: BoolDomain) -> Self {         TagDomain {             map: self.map.insert(tag, val),+            default: self.default,         }     }      /// Return a lifted Boolean that indicates the presence of `tag` in the tag domain element.     #[logfn_inputs(TRACE)]     pub fn has_tag(&self, tag: &Tag) -> BoolDomain {-        *self.map.get(tag).unwrap_or(&BoolDomain::False)+        *self.map.get(tag).unwrap_or(&self.default)

I'm not sure whether the caller can easily figure things out. Consider the program below:

let temp = local + param;
verify!(has_tag!(&temp, Taint));

If the tag sets for both local and param are empty, the function call to has_tag returns "tag is not present". Then the caller would like to figure out whether the tag is absent or unknown. But this depends on the propagation behavior of Taint:

  • If the addition + blocks Taint, then temp does not have Taint.
  • Otherwise, if the addition + propagates Taint, then whether temp has Taint or not is unknown.
stonebuddha

comment created time in 17 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 impl TagDomain {     pub fn add_tag(&self, tag: Tag, val: BoolDomain) -> Self {         TagDomain {             map: self.map.insert(tag, val),+            default: self.default,         }     }      /// Return a lifted Boolean that indicates the presence of `tag` in the tag domain element.     #[logfn_inputs(TRACE)]     pub fn has_tag(&self, tag: &Tag) -> BoolDomain {-        *self.map.get(tag).unwrap_or(&BoolDomain::False)+        *self.map.get(tag).unwrap_or(&self.default)

I guess the issue here is that whether has_tag can already decide the result or not. If has_tag indeed needs information from the callers, we should let the callers make the decision.

stonebuddha

comment created time in 17 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 impl TagDomain {     pub fn add_tag(&self, tag: Tag, val: BoolDomain) -> Self {         TagDomain {             map: self.map.insert(tag, val),+            default: self.default,         }     }      /// Return a lifted Boolean that indicates the presence of `tag` in the tag domain element.     #[logfn_inputs(TRACE)]     pub fn has_tag(&self, tag: &Tag) -> BoolDomain {-        *self.map.get(tag).unwrap_or(&BoolDomain::False)+        *self.map.get(tag).unwrap_or(&self.default)

Well, it might work if has_tag just returns if the tag map contains the entry or not, and all the callers of has_tag do their job to distinguish false and unknown.

stonebuddha

comment created time in 17 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 impl TagDomain {     pub fn add_tag(&self, tag: Tag, val: BoolDomain) -> Self {         TagDomain {             map: self.map.insert(tag, val),+            default: self.default,         }     }      /// Return a lifted Boolean that indicates the presence of `tag` in the tag domain element.     #[logfn_inputs(TRACE)]     pub fn has_tag(&self, tag: &Tag) -> BoolDomain {-        *self.map.get(tag).unwrap_or(&BoolDomain::False)+        *self.map.get(tag).unwrap_or(&self.default)

Returning either Bottom or Top will presumably fail the following test:

let non_secret = 12345;
verify!(does_not_have_tag(&non_secret, Taint));
stonebuddha

comment created time in 17 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 impl AbstractValueTrait for Rc<AbstractValue> {                     default.clone()                 }             }+            Expression::UnknownTagCheck {+                path,+                tag,+                checking_presence,+            } => {+                if let Some(val) = environment.value_at(&path) {+                    let tag_presence = val.has_tag(tag);

By "callers of has_tag" I also mean the refinement routine itself.

stonebuddha

comment created time in 17 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 impl TagDomain {     pub fn add_tag(&self, tag: Tag, val: BoolDomain) -> Self {         TagDomain {             map: self.map.insert(tag, val),+            default: self.default,         }     }      /// Return a lifted Boolean that indicates the presence of `tag` in the tag domain element.     #[logfn_inputs(TRACE)]     pub fn has_tag(&self, tag: &Tag) -> BoolDomain {-        *self.map.get(tag).unwrap_or(&BoolDomain::False)+        *self.map.get(tag).unwrap_or(&self.default)

Yes, so the default field is only used to control tags that are not yet known. But there are two different situations:

  • A local variable should initially have no tags.
  • A function parameter should mark the presence of every tag as "not yet known".
stonebuddha

comment created time in 17 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 pub struct Tag {  /// An element of the tag domain is essentially an over-approximation for present and absent tags. /// The approximation is denoted as a map from tags to lifted Boolean values (`BoolDomain`).+/// Unrecorded tags are mapped to the `default` field of the tag domain element. /// If a tag is mapped to `True`, then it must be present. /// If a tag is mapped to `False', then it must be absent. /// If a tag is mapped to `Top`, then it may or may not be present. #[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Clone, Serialize, Deserialize)] pub struct TagDomain {     map: RedBlackTreeMap<Tag, BoolDomain>,+    default: BoolDomain,

The default field is used to answer tag queries. If a tag is kept track in the map, we just look it up in the map; otherwise, we use the default as the check result.

stonebuddha

comment created time in 17 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 impl TagDomain {     pub fn add_tag(&self, tag: Tag, val: BoolDomain) -> Self {         TagDomain {             map: self.map.insert(tag, val),+            default: self.default,         }     }      /// Return a lifted Boolean that indicates the presence of `tag` in the tag domain element.     #[logfn_inputs(TRACE)]     pub fn has_tag(&self, tag: &Tag) -> BoolDomain {-        *self.map.get(tag).unwrap_or(&BoolDomain::False)+        *self.map.get(tag).unwrap_or(&self.default)

If a tag is never attached to a value, the tap map will not have an entry for the tag. This is the reason why I put BoolDomain::False previously.

But the change in CallVisitor::handle_has_tag introduces a problem. Previously if a path is not in the environment, we construct an unknown tag check. Now the use of lookup_path_and_refine_result may return a variable, whose tag map should indeed be TOP.

Therefore, I want get_tags to return a tag domain element that maps every tag to TOP. To achieve that, I introduce the default field in TagDomain.

stonebuddha

comment created time in 17 days

Pull request review commentfacebookexperimental/MIRAI

Add an expression kind for unknown tag checks

 impl AbstractValueTrait for Rc<AbstractValue> {                     default.clone()                 }             }+            Expression::UnknownTagCheck {+                path,+                tag,+                checking_presence,+            } => {+                if let Some(val) = environment.value_at(&path) {+                    let tag_presence = val.has_tag(tag);

The logic is implemented by the callers of has_tag. I'm thinking about replacing BoolDomain with AbstractValue in tag domain elements for a better control of tag checking.

stonebuddha

comment created time in 17 days

more