19.11.2016 Views

Technical Analysis of the Pegasus Exploits on iOS

eNQc3Ry

eNQc3Ry

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

void MarkedArgumentBuffer::slowAppend(JSValue v)<br />

{<br />

int newCapacity = m_capacity * 4;<br />

EncodedJSValue* newBuffer = new EncodedJSValue[newCapacity];<br />

for (int i = 0; i < m_capacity; ++i)<br />

newBuffer[i] = m_buffer[i];<br />

if (EncodedJSValue* base = mallocBase())<br />

delete [] base;<br />

m_buffer = newBuffer;<br />

m_capacity = newCapacity;<br />

Once <str<strong>on</strong>g>the</str<strong>on</strong>g> underlying buffer has moved to <str<strong>on</strong>g>the</str<strong>on</strong>g> heap, values are not automatically protected from<br />

garbage collecti<strong>on</strong>. To ensure that <str<strong>on</strong>g>the</str<strong>on</strong>g>se objects are not deallocated, <str<strong>on</strong>g>the</str<strong>on</strong>g> garbage collector<br />

performs a MarkingArgumentBuffers phase in which each value c<strong>on</strong>tained within a<br />

MarkedArgumentBuffer that has been added to <str<strong>on</strong>g>the</str<strong>on</strong>g> Heap’s m_markListSet is marked (marking a<br />

cell ensures that it will not be deallocated in a particular garbage collecti<strong>on</strong> cycle). For this<br />

method <str<strong>on</strong>g>of</str<strong>on</strong>g> marking to work, <str<strong>on</strong>g>the</str<strong>on</strong>g> MarkedArgumentBuffer must be added to <str<strong>on</strong>g>the</str<strong>on</strong>g> markListSet at <str<strong>on</strong>g>the</str<strong>on</strong>g><br />

same time that <str<strong>on</strong>g>the</str<strong>on</strong>g> MarkedArgumentBuffer’s underlying values are moved to <str<strong>on</strong>g>the</str<strong>on</strong>g> heap.<br />

// As l<strong>on</strong>g as our size stays within our Vector's inline<br />

// capacity, all our values are allocated <strong>on</strong> <str<strong>on</strong>g>the</str<strong>on</strong>g> stack, and<br />

// <str<strong>on</strong>g>the</str<strong>on</strong>g>refore d<strong>on</strong>'t need explicit marking. Once our size exceeds<br />

// our Vector's inline capacity, though, our values move to <str<strong>on</strong>g>the</str<strong>on</strong>g><br />

// heap, where <str<strong>on</strong>g>the</str<strong>on</strong>g>y do need explicit marking.<br />

for (int i = 0; i < m_size; ++i) {<br />

Heap* heap = Heap::heap(JSValue::decode(slotFor(i)));<br />

if (!heap)<br />

c<strong>on</strong>tinue;<br />

}<br />

m_markSet = &heap->markListSet();<br />

m_markSet->add(this);<br />

break;<br />

The above code attempts to acquire <str<strong>on</strong>g>the</str<strong>on</strong>g> heap c<strong>on</strong>text for a value and add <str<strong>on</strong>g>the</str<strong>on</strong>g><br />

MarkedArgumentBuffer to <str<strong>on</strong>g>the</str<strong>on</strong>g> Heap’s markListSet. However, this is <strong>on</strong>ly attempted <strong>on</strong>ce for <str<strong>on</strong>g>the</str<strong>on</strong>g><br />

ninth value added to <str<strong>on</strong>g>the</str<strong>on</strong>g> MarkedArgumentBuffer.<br />

inline Heap* Heap::heap(c<strong>on</strong>st JSValue v)<br />

{<br />

if (!v.isCell())<br />

return 0;<br />

return heap(v.asCell());<br />

}<br />

A JSValue c<strong>on</strong>tains a tag which describes <str<strong>on</strong>g>the</str<strong>on</strong>g> type <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> value that it encodes. In <str<strong>on</strong>g>the</str<strong>on</strong>g> case <str<strong>on</strong>g>of</str<strong>on</strong>g><br />

complex objects this tag will be CellTag and <str<strong>on</strong>g>the</str<strong>on</strong>g> JSValue will encode a pointer to an underlying<br />

item <strong>on</strong> <str<strong>on</strong>g>the</str<strong>on</strong>g> Heap. Alternatively, for simple types where <str<strong>on</strong>g>the</str<strong>on</strong>g> entire underlying value <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g><br />

variable can be encoded directly into a JSValue (ex. Integers, Booleans, null, and undefined),<br />

storing <str<strong>on</strong>g>the</str<strong>on</strong>g> value <strong>on</strong> <str<strong>on</strong>g>the</str<strong>on</strong>g> heap would be redundant and a different identifying tag will be used.<br />

The functi<strong>on</strong> JSValue::isCell() is used to determine whe<str<strong>on</strong>g>the</str<strong>on</strong>g>r a JSValue encodes a pointer to a<br />

Page 5

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!