diff --git a/infer/src/pulse/PulseModels.ml b/infer/src/pulse/PulseModels.ml index ac402d74d..fbbcd713f 100644 --- a/infer/src/pulse/PulseModels.ml +++ b/infer/src/pulse/PulseModels.ml @@ -404,25 +404,27 @@ module GenericArrayBackedCollectionIterator = struct let operator_star ~desc iter ~caller_summary:_ ~callee_procname:_ location ~ret astate = let event = ValueHistory.Call {f= Model desc; location; in_call= []} in - let* astate, iter_index = to_internal_pointer location iter astate in - let+ astate, (elem_val, elem_hist) = - GenericArrayBackedCollection.element location iter (fst iter_index) astate + let* astate, (iter_index_addr, iter_index_hist) = to_internal_pointer location iter astate in + let+ astate, (elem_val, _) = + GenericArrayBackedCollection.element location iter iter_index_addr astate in - let astate = PulseOperations.write_id (fst ret) (elem_val, event :: elem_hist) astate in + let astate = PulseOperations.write_id (fst ret) (elem_val, event :: iter_index_hist) astate in [ExecutionDomain.ContinueProgram astate] let operator_plus_plus ~desc iter ~caller_summary:_ ~callee_procname:_ location ~ret:_ astate = let event = ValueHistory.Call {f= Model desc; location; in_call= []} in let index_next = AbstractValue.mk_fresh () in - let* astate, current_index = to_internal_pointer location iter astate in + let* astate, (current_index, current_index_hist) = to_internal_pointer location iter astate in let* astate, element = - GenericArrayBackedCollection.element location iter (fst current_index) astate + GenericArrayBackedCollection.element location iter current_index astate in (* Iterator is invalid if the value it points to is invalid *) - let* astate, _ = PulseOperations.eval_access location element Dereference astate in + let* astate, _ = + PulseOperations.eval_access location (fst element, current_index_hist) Dereference astate + in PulseOperations.write_field location ~ref:iter internal_pointer - ~obj:(index_next, [event]) + ~obj:(index_next, event :: current_index_hist) astate >>| ExecutionDomain.continue >>| List.return end @@ -476,16 +478,16 @@ module StdVector = struct let astate = PulseArithmetic.and_eq_int (Immediate {location; history= []}) index_zero IntLit.zero astate in - let* astate, ((arr_addr, hist) as arr) = + let* astate, ((arr_addr, _) as arr) = GenericArrayBackedCollection.eval location vector astate in let* astate, _ = GenericArrayBackedCollection.eval_element location arr index_zero astate in PulseOperations.write_field location ~ref:iter GenericArrayBackedCollection.field - ~obj:(arr_addr, event :: hist) + ~obj:(arr_addr, event :: snd iter) astate >>= PulseOperations.write_field location ~ref:iter GenericArrayBackedCollectionIterator.internal_pointer - ~obj:(index_zero, [event]) + ~obj:(index_zero, event :: snd iter) >>| ExecutionDomain.continue >>| List.return diff --git a/infer/tests/codetoanalyze/cpp/pulse/issues.exp b/infer/tests/codetoanalyze/cpp/pulse/issues.exp index a17a07420..6a726c298 100644 --- a/infer/tests/codetoanalyze/cpp/pulse/issues.exp +++ b/infer/tests/codetoanalyze/cpp/pulse/issues.exp @@ -87,7 +87,7 @@ codetoanalyze/cpp/pulse/vector.cpp, insert_bad, 3, VECTOR_INVALIDATION, no_bucke codetoanalyze/cpp/pulse/vector.cpp, push_back_loop_bad, 6, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,variable `vec` declared here,was potentially invalidated by `std::vector::push_back()`,use-after-lifetime part of the trace starts here,variable `vec` declared here,passed as argument to `std::vector::at()` (modelled),return from call to `std::vector::at()` (modelled),assigned,invalid access occurs here] codetoanalyze/cpp/pulse/vector.cpp, reserve_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `vec` of reserve_bad,was potentially invalidated by `std::vector::reserve()`,use-after-lifetime part of the trace starts here,parameter `vec` of reserve_bad,passed as argument to `std::vector::at()` (modelled),return from call to `std::vector::at()` (modelled),assigned,invalid access occurs here] codetoanalyze/cpp/pulse/vector.cpp, shrink_to_fit_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `vec` of shrink_to_fit_bad,was potentially invalidated by `std::vector::shrink_to_fit()`,use-after-lifetime part of the trace starts here,parameter `vec` of shrink_to_fit_bad,passed as argument to `std::vector::at()` (modelled),return from call to `std::vector::at()` (modelled),assigned,invalid access occurs here] -codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_after_push_back_loop_bad, 9, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,variable `vec` declared here,was potentially invalidated by `std::vector::push_back()`,use-after-lifetime part of the trace starts here,variable `vec` declared here,passed as argument to `iterator operator*` (modelled),return from call to `iterator operator*` (modelled),invalid access occurs here] -codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_next_after_emplace_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `vec` of iterator_next_after_emplace_bad,was potentially invalidated by `std::vector::emplace()`,use-after-lifetime part of the trace starts here,parameter `vec` of iterator_next_after_emplace_bad,invalid access occurs here] -codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_next_after_emplace_loop_bad, 2, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `vec` of iterator_next_after_emplace_loop_bad,was potentially invalidated by `std::vector::emplace()`,use-after-lifetime part of the trace starts here,parameter `vec` of iterator_next_after_emplace_loop_bad,invalid access occurs here] -codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_read_after_emplace_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `vec` of iterator_read_after_emplace_bad,was potentially invalidated by `std::vector::emplace()`,use-after-lifetime part of the trace starts here,parameter `vec` of iterator_read_after_emplace_bad,passed as argument to `iterator operator*` (modelled),return from call to `iterator operator*` (modelled),invalid access occurs here] +codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_after_push_back_loop_bad, 9, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,variable `vec` declared here,was potentially invalidated by `std::vector::push_back()`,use-after-lifetime part of the trace starts here,variable `iter_begin` declared here,passed as argument to `std::vector::begin()` (modelled),return from call to `std::vector::begin()` (modelled),passed as argument to `iterator constructor` (modelled),return from call to `iterator constructor` (modelled),passed as argument to `iterator operator*` (modelled),return from call to `iterator operator*` (modelled),invalid access occurs here] +codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_next_after_emplace_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `vec` of iterator_next_after_emplace_bad,was potentially invalidated by `std::vector::emplace()`,use-after-lifetime part of the trace starts here,variable `iter` declared here,passed as argument to `std::vector::begin()` (modelled),return from call to `std::vector::begin()` (modelled),invalid access occurs here] +codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_next_after_emplace_loop_bad, 2, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `vec` of iterator_next_after_emplace_loop_bad,was potentially invalidated by `std::vector::emplace()`,use-after-lifetime part of the trace starts here,variable `iter` declared here,passed as argument to `std::vector::begin()` (modelled),return from call to `std::vector::begin()` (modelled),invalid access occurs here] +codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_read_after_emplace_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `vec` of iterator_read_after_emplace_bad,was potentially invalidated by `std::vector::emplace()`,use-after-lifetime part of the trace starts here,variable `iter` declared here,passed as argument to `std::vector::begin()` (modelled),return from call to `std::vector::begin()` (modelled),passed as argument to `iterator operator*` (modelled),return from call to `iterator operator*` (modelled),invalid access occurs here]