Fix: symbolic locksets use may-equality when invalidating on unlock#1987
Fix: symbolic locksets use may-equality when invalidating on unlock#1987
Conversation
…operations The previous implementation used must-equality (via EqualSet query) to determine which locks to remove when a mutex is unlocked. This was unsound: if the unlock expression is a pointer that may point to one of several mutexes, none of them would be removed from the lockset (since no must-equal address could be determined). The fix: use MayPointTo query to check may-equality. A lock l is removed from the lockset when unlocking e if MayPointTo(e) and MayPointTo(l) have a common element, i.e., e may evaluate to the same address as l. This correctly handles cases like: pthread_mutex_t *m = &mutex1; if (i) m = &mutex2; pthread_mutex_lock(&mutex1); pthread_mutex_unlock(m); // should remove &mutex1 since m may be &mutex1 // global is now possibly unprotected (UNKNOWN/race) Test cases: 23-sound_unlock_racing.c and 24-sound_lock_racing.c already exist and test this exact scenario. Agent-Logs-Url: https://github.com/goblint/analyzer/sessions/1c6cf47d-0ab6-48a7-93e9-cfda3414fd03 Co-authored-by: michael-schwarz <13812333+michael-schwarz@users.noreply.github.com>
|
@copilot You should remove the "todo" in the comment for tests/regression/06-symbeq/30-symb_lockset_mayunlock.c, and make sure that test passes now. |
…th may-equality fix The unlock of &p2->mymutex (where p2 may be NULL or p1) now correctly removes &p1->mymutex from the lockset via MayPointTo may-equality check, making the subsequent p1->myint++ correctly detected as a race condition. Agent-Logs-Url: https://github.com/goblint/analyzer/sessions/644f1b44-5460-4a93-89cf-0770892d1b67 Co-authored-by: vesalvojdani <911273+vesalvojdani@users.noreply.github.com>
Removed the |
| let pt_e = ask.f (Queries.MayPointTo e) in | ||
| S.filter (fun l -> | ||
| let pt_l = ask.f (Queries.MayPointTo l) in | ||
| Queries.AD.is_bot (Queries.AD.meet pt_e pt_l) |
There was a problem hiding this comment.
This seems like a roundabout form of semantic_equal.
There was a problem hiding this comment.
Good point. For AddrOf(Var v, o) lockset elements (concrete variable addresses), I now use Queries.AD.Addr.semantic_equal directly instead of the roundabout MayPointTo l + AD.meet + is_bot pattern. The Addr.t is constructed via Addr.of_mval (v, ValueDomain.Offs.of_exp (Offset.Exp.of_cil o)), and we keep l iff every address in pt_e is definitely not addr_l (semantic_equal = Some false). For other AddrOf(Mem …) expressions, the MayPointTo l + AD.meet + is_bot fallback is still used. Done in b430e2c.
| S.union addrs st | ||
| let remove ask e st = | ||
| (* TODO: Removing based on must-equality sets is not sound! *) | ||
| let no_casts = S.map Expcompare.stripCastsDeepForPtrArith (eq_set ask e) in |
There was a problem hiding this comment.
I wonder what the purpose of stripCastsDeepForPtrArith was because it's now removed from remove.
It's still in add though. I don't immediately know if this mismatch/removal can cause any problems.
There was a problem hiding this comment.
stripCastsDeepForPtrArith in add was used to normalize expressions from eq_set before syntactic comparison with lockset elements. In remove, we now use MayPointTo which evaluates expressions through the abstract domain and handles casts semantically, so the explicit cast-stripping is no longer needed. Added a comment in b430e2c explaining this.
There was a problem hiding this comment.
The EqualSet query (implemented in varEq.ml) wraps every returned expression in CastE (Internal, et, ...) (see varEq.ml:548). So stripCastsDeepForPtrArith in add is needed to peel those cast wrappers before the AddrOf _ syntactic filter can recognize the lock addresses to store.
In remove, we use MayPointTo instead, which evaluates through the abstract value domain — casts are handled semantically there, so no explicit stripping is needed.
|
@copilot: Address Simmo's comments |
…lic.remove Agent-Logs-Url: https://github.com/goblint/analyzer/sessions/d47c54f5-c04d-47f7-a70e-cafdaae31310 Co-authored-by: michael-schwarz <13812333+michael-schwarz@users.noreply.github.com>
Symbolic.removeinsymbLocksDomain.mlto useMayPointTofor may-equality checktests/regression/06-symbeq/30-symb_lockset_mayunlock.c— race is now correctly detected with the may-equality fixAddrOf(Var v, o)lockset elements, useQueries.AD.Addr.semantic_equaldirectly instead of the roundaboutMayPointTo l+AD.meet + is_botpatternstripCastsDeepForPtrArithis not needed inremove(MayPointTo handles casts semantically)semantic_equal = Some falsecondition