This class represents a write action that can be carried out by a single format string specifier. Each write has an address (start), a size and the integer that should be written. Additionally writes can have a mask to specify which bits are important. While the write always overw
| 160 | # 00 00 05 05 00 05 -> need overlapping writes if numbwritten > 5 |
| 161 | |
| 162 | class AtomWrite(object): |
| 163 | """ |
| 164 | This class represents a write action that can be carried out by a single format string specifier. |
| 165 | |
| 166 | Each write has an address (start), a size and the integer that should be written. |
| 167 | |
| 168 | Additionally writes can have a mask to specify which bits are important. |
| 169 | While the write always overwrites all bytes in the range [start, start+size) the mask sometimes allows more |
| 170 | efficient execution. For example, assume the current format string counter is at 0xaabb and a write with |
| 171 | with integer = 0xaa00 and mask = 0xff00 needs to be executed. In that case, since the lower byte is not covered |
| 172 | by the mask, the write can be directly executed with a %hn sequence (so we will write 0xaabb, but that is ok |
| 173 | because the mask only requires the upper byte to be correctly written). |
| 174 | """ |
| 175 | __slots__ = ( "start", "size", "integer", "mask" ) |
| 176 | |
| 177 | def __init__(self, start, size, integer, mask=None): |
| 178 | if mask is None: |
| 179 | mask = (1 << (8 * size)) - 1 |
| 180 | self.start = int(start) |
| 181 | self.size = size |
| 182 | self.integer = int(integer) |
| 183 | self.mask = int(mask) |
| 184 | |
| 185 | def __len__(self): |
| 186 | return self.size |
| 187 | |
| 188 | def __key(self): |
| 189 | return (self.start, self.size, self.integer, self.mask) |
| 190 | |
| 191 | def __eq__(self, other): |
| 192 | if not isinstance(other, AtomWrite): |
| 193 | raise TypeError("comparision not supported between instances of '%s' and '%s'" % (type(self), type(other))) |
| 194 | return self.__key() == other.__key() |
| 195 | |
| 196 | def __ne__(self, other): |
| 197 | return not self.__eq__(other) |
| 198 | |
| 199 | def __hash__(self): |
| 200 | return hash(self.__key()) |
| 201 | |
| 202 | def __repr__(self): |
| 203 | return "AtomWrite(start=%d, size=%d, integer=%#x, mask=%#x)" % (self.start, self.size, self.integer, self.mask) |
| 204 | |
| 205 | @property |
| 206 | def bitsize(self): |
| 207 | return self.size * 8 |
| 208 | |
| 209 | @property |
| 210 | def end(self): |
| 211 | return self.start + self.size |
| 212 | |
| 213 | def compute_padding(self, counter): |
| 214 | """ |
| 215 | This function computes the least amount of padding necessary to execute this write, |
| 216 | given the current format string write counter (how many bytes have been written until now). |
| 217 | |
| 218 | Examples: |
| 219 |
no outgoing calls
no test coverage detected