Fix ClemoryView.find translating its bounds twice - #820
Conversation
find clamped search_min and search_max against self._start and self._end, which are addresses in the parent's space, and then added self._rebase to them, so a default search ran over a range that is not the view's. For a view of 0x1000-0x1010 built with the default offset it searched the parent's 0x2000-0x2010 and reported nothing; where the offset happens to equal the start, _rebase is zero and the old arithmetic came out right by accident. It also yielded the parent's addresses rather than the view's, so unless _rebase is zero a match could not be handed back to __getitem__ or load. Every other method of the class takes and returns addresses in the view's space. Clamp against _offset and _endoffset, which are the view's own bounds, and subtract _rebase from each result.
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head
No corpus comparison is offered. No loader path constructs a Workspace gate: not run. What ran instead is the scoped equivalent above: cle's own suite in an isolated Caveats: |
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Searching through a Before — the view reports nothing where the parent reports a match: cle master 0e77adeAfter — the view reports that match at the offset that indexes it: with this change |
|
Corpus decompilation diffs can be found at angr/dec-snapshots@master...angr/cle_820 |
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Problem
ClemoryView.findreports nothing where the parentClemoryfinds a match:An empty result reads as an answer rather than a failure, so a caller searching through a view
gets a wrong one silently.
Root cause
The bounds are translated twice.
search_minandsearch_maxare clamped againstself._startandself._end, which are addresses in the parent's space, and thenself._rebaseis added to them:For the view above
_rebaseis0x1000, so a default search runs over the parent's0x2000-0x2010, which is past the end of the view and past the end of the backer. Which wayit goes wrong depends on the
offset: whereoffsetequalsstart,_rebaseis zero and thearithmetic comes out right by accident.
__getitem__,__setitem__,loadandstoreall take an address in the view's space and add_rebaseonce; onlyfindstarts from the parent's.The results have the same problem in the other direction:
findyields the parent's addresses,so unless
_rebaseis zero a match cannot be handed back toview[...].Fix
Clamp against
self._offsetandself._endoffset, which are the view's own bounds, andsubtract
_rebasefrom each result.findtakes and gives addresses in the view's space, likethe rest of the class.
This does not touch
Clemory.find, which has bound bugs of its own that the view inheritseither way.
Nothing in
cle,angrorangr-managementconstructs aClemoryView, so this has noin-tree caller; the class is exported from
cleand the method is wrong for anyone who does.Testing
tests/test_clemory.pygainstest_clemory_view_find: that the view reports the match at theoffset that indexes it, that the byte there is the one expected, that a
search_maxbelow thematch excludes it, that a view built with a non-zero
offsetreports the match at that offset,and that a view starting inside a backer reports only the match its window covers and not one
before it. It fails on master with
assert [] == [8].Validation: #820 (comment)
session: sharpen