@@ -504,6 +504,16 @@ tests = testGroup "hevm"
504504 let e = ReadByte (Lit 0x0 ) (WriteWord (Lit 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd ) (Lit 0x0 ) (ConcreteBuf " \255\255\255\255" ))
505505 b <- checkEquiv e (Expr. simplify e)
506506 assertBoolM " Simplifier failed" b
507+ , test " copyslice-simps" $ do
508+ let e a b = CopySlice (Lit 0 ) (Lit 0 ) (BufLength (AbstractBuf " buff" )) (CopySlice (Lit 0 ) (Lit 0 ) (BufLength (AbstractBuf " buff" )) (AbstractBuf " buff" ) (ConcreteBuf a)) (ConcreteBuf b)
509+ expr1 = e " " " "
510+ expr2 = e " " " aasdfasdf"
511+ expr3 = e " 9832478932" " "
512+ expr4 = e " 9832478932" " aasdfasdf"
513+ assertEqualM " Not full simp" (Expr. simplify expr1) (AbstractBuf " buff" )
514+ assertEqualM " Not full simp" (Expr. simplify expr2) $ CopySlice (Lit 0x0 ) (Lit 0x0 ) (BufLength (AbstractBuf " buff" )) (AbstractBuf " buff" ) (ConcreteBuf " aasdfasdf" )
515+ assertEqualM " Not full simp" (Expr. simplify expr3) (AbstractBuf " buff" )
516+ assertEqualM " Not full simp" (Expr. simplify expr4) $ CopySlice (Lit 0x0 ) (Lit 0x0 ) (BufLength (AbstractBuf " buff" )) (AbstractBuf " buff" ) (ConcreteBuf " aasdfasdf" )
507517 , test " buffer-length-copy-slice-beyond-source1" $ do
508518 let e = BufLength (CopySlice (Lit 0x2 ) (Lit 0x2 ) (Lit 0x1 ) (ConcreteBuf " a" ) (ConcreteBuf " " ))
509519 b <- checkEquiv e (Expr. simplify e)
@@ -2290,6 +2300,99 @@ tests = testGroup "hevm"
22902300 assertEqualM " number of counterexamples" 1 numCexes
22912301 assertEqualM " number of errors" 0 numErrs
22922302 assertEqualM " number of qed-s" 0 numQeds
2303+ , test " copyslice-symbolic-ok" $ do
2304+ Just c <- solcRuntime " C"
2305+ [i |
2306+ contract Target {
2307+ function get(address addr) external view returns (uint256) {
2308+ return 55;
2309+ }
2310+ }
2311+ contract C {
2312+ function retFor(address addr) public returns (uint256) {
2313+ Target mm = new Target();
2314+ uint256 ret = mm.get(addr);
2315+ assert(ret == 4);
2316+ return ret;
2317+ }
2318+ }
2319+ |]
2320+ let sig2 = Just (Sig " retFor(address)" [AbiAddressType ])
2321+ (expr, ret) <- withDefaultSolver $ \ s -> checkAssert s defaultPanicCodes c sig2 [] defaultVeriOpts
2322+ putStrLnM $ " successfully explored: " <> show (Expr. numBranches expr) <> " paths"
2323+ assertBoolM " The expression is NOT error" $ not $ any isError ret
2324+ -- NOTE: below used to be symbolic copyslice copy error before new copyslice
2325+ -- simplifications in Expr.simplify
2326+ , test " overapproximates-undeployed-contract" $ do
2327+ Just c <- solcRuntime " C"
2328+ [i |
2329+ contract Target {
2330+ function get(address addr) external view returns (uint256) {
2331+ return 55;
2332+ }
2333+ }
2334+ contract C {
2335+ Target mm;
2336+ function retFor(address addr) public returns (uint256) {
2337+ // NOTE: this is symbolic execution, and no setUp has been ran
2338+ // hence, this below calls unknown code! So it overapproximates.
2339+ // mm is actually 0 here, which we may want to give a warning for
2340+ uint256 ret = mm.get(addr);
2341+ assert(ret == 4);
2342+ return ret;
2343+ }
2344+ }
2345+ |]
2346+ let sig2 = Just (Sig " retFor(address)" [AbiAddressType ])
2347+ (expr, ret) <- withDefaultSolver $ \ s -> checkAssert s defaultPanicCodes c sig2 [] defaultVeriOpts
2348+ putStrLnM $ " successfully explored: " <> show (Expr. numBranches expr) <> " paths"
2349+ assertBoolM " The expression is NOT error" $ not $ any isError ret
2350+ let numCexes = sum $ map (fromEnum . isCex) ret
2351+ -- There are 2 CEX-es
2352+ -- This is because with one CEX, the return DATA
2353+ -- is empty, and in the other, the return data is non-empty (but symbolic)
2354+ assertEqualM " number of counterexamples" 2 numCexes
2355+ , test " staticcall-no-overapprox-2" $ do
2356+ Just c <- solcRuntime " C"
2357+ [i |
2358+ contract Target {
2359+ function add(uint256 x, uint256 y) external pure returns (uint256) {
2360+ unchecked {
2361+ return x + y;
2362+ }
2363+ }
2364+ }
2365+ contract C {
2366+ function checkval(uint256 x, uint256 y) public {
2367+ Target t = new Target();
2368+ address realAddr = address(t);
2369+ bytes memory data = abi.encodeWithSignature("add(uint256,uint256)", x, y);
2370+ (bool success, bytes memory returnData) = realAddr.staticcall(data);
2371+ assert(success);
2372+ assert(returnData.length == 32);
2373+
2374+ // Decode the return value
2375+ uint256 result = abi.decode(returnData, (uint256));
2376+
2377+ // Assert that the result is equal to x + y
2378+ unchecked {
2379+ assert(result == x + y);
2380+ }
2381+ }
2382+ }
2383+ |]
2384+ let sig = Just (Sig " checkval(uint256,uint256)" [AbiUIntType 256 , AbiUIntType 256 ])
2385+ (res, ret) <- withDefaultSolver $ \ s -> checkAssert s defaultPanicCodes c sig [] defaultVeriOpts
2386+ putStrLnM $ " successfully explored: " <> show (Expr. numBranches res) <> " paths"
2387+ assertBoolM " The expression is NOT partial" $ not $ Expr. containsNode isPartial res
2388+ assertBoolM " The expression is NOT unknown" $ not $ any isUnknown ret
2389+ assertBoolM " The expression is NOT error" $ not $ any isError ret
2390+ let numCexes = sum $ map (fromEnum . isCex) ret
2391+ let numErrs = sum $ map (fromEnum . isError) ret
2392+ let numQeds = sum $ map (fromEnum . isQed) ret
2393+ assertEqualM " number of counterexamples" 0 numCexes
2394+ assertEqualM " number of errors" 0 numErrs
2395+ assertEqualM " number of qed-s" 1 numQeds
22932396 , test " staticcall-check-symbolic1" $ do
22942397 Just c <- solcRuntime " C"
22952398 [i |
0 commit comments