Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | #include <stdlib.h> |
michael@0 | 2 | #include <string.h> |
michael@0 | 3 | |
michael@0 | 4 | #include "ia32_invariant.h" |
michael@0 | 5 | #include "ia32_insn.h" |
michael@0 | 6 | #include "ia32_settings.h" |
michael@0 | 7 | |
michael@0 | 8 | extern ia32_table_desc_t *ia32_tables; |
michael@0 | 9 | extern ia32_settings_t ia32_settings; |
michael@0 | 10 | |
michael@0 | 11 | extern size_t ia32_table_lookup( unsigned char *buf, size_t buf_len, |
michael@0 | 12 | unsigned int table, ia32_insn_t **raw_insn, |
michael@0 | 13 | unsigned int *prefixes ); |
michael@0 | 14 | |
michael@0 | 15 | |
michael@0 | 16 | /* -------------------------------- ModR/M, SIB */ |
michael@0 | 17 | /* Convenience flags */ |
michael@0 | 18 | #define MODRM_EA 1 /* ModR/M is an effective addr */ |
michael@0 | 19 | #define MODRM_reg 2 /* ModR/M is a register */ |
michael@0 | 20 | |
michael@0 | 21 | /* ModR/M flags */ |
michael@0 | 22 | #define MODRM_RM_SIB 0x04 /* R/M == 100 */ |
michael@0 | 23 | #define MODRM_RM_NOREG 0x05 /* R/B == 101 */ |
michael@0 | 24 | /* if (MODRM.MOD_NODISP && MODRM.RM_NOREG) then just disp32 */ |
michael@0 | 25 | #define MODRM_MOD_NODISP 0x00 /* mod == 00 */ |
michael@0 | 26 | #define MODRM_MOD_DISP8 0x01 /* mod == 01 */ |
michael@0 | 27 | #define MODRM_MOD_DISP32 0x02 /* mod == 10 */ |
michael@0 | 28 | #define MODRM_MOD_NOEA 0x03 /* mod == 11 */ |
michael@0 | 29 | /* 16-bit modrm flags */ |
michael@0 | 30 | #define MOD16_MOD_NODISP 0 |
michael@0 | 31 | #define MOD16_MOD_DISP8 1 |
michael@0 | 32 | #define MOD16_MOD_DISP16 2 |
michael@0 | 33 | #define MOD16_MOD_REG 3 |
michael@0 | 34 | |
michael@0 | 35 | #define MOD16_RM_BXSI 0 |
michael@0 | 36 | #define MOD16_RM_BXDI 1 |
michael@0 | 37 | #define MOD16_RM_BPSI 2 |
michael@0 | 38 | #define MOD16_RM_BPDI 3 |
michael@0 | 39 | #define MOD16_RM_SI 4 |
michael@0 | 40 | #define MOD16_RM_DI 5 |
michael@0 | 41 | #define MOD16_RM_BP 6 |
michael@0 | 42 | #define MOD16_RM_BX 7 |
michael@0 | 43 | |
michael@0 | 44 | /* SIB flags */ |
michael@0 | 45 | #define SIB_INDEX_NONE 0x04 |
michael@0 | 46 | #define SIB_BASE_EBP 0x05 |
michael@0 | 47 | #define SIB_SCALE_NOBASE 0x00 |
michael@0 | 48 | |
michael@0 | 49 | /* Convenience struct for modR/M bitfield */ |
michael@0 | 50 | struct modRM_byte { |
michael@0 | 51 | unsigned int mod : 2; |
michael@0 | 52 | unsigned int reg : 3; |
michael@0 | 53 | unsigned int rm : 3; |
michael@0 | 54 | }; |
michael@0 | 55 | |
michael@0 | 56 | /* Convenience struct for SIB bitfield */ |
michael@0 | 57 | struct SIB_byte { |
michael@0 | 58 | unsigned int scale : 2; |
michael@0 | 59 | unsigned int index : 3; |
michael@0 | 60 | unsigned int base : 3; |
michael@0 | 61 | }; |
michael@0 | 62 | |
michael@0 | 63 | #ifdef WIN32 |
michael@0 | 64 | static void byte_decode(unsigned char b, struct modRM_byte *modrm) { |
michael@0 | 65 | #else |
michael@0 | 66 | static inline void byte_decode(unsigned char b, struct modRM_byte *modrm) { |
michael@0 | 67 | #endif |
michael@0 | 68 | /* generic bitfield-packing routine */ |
michael@0 | 69 | |
michael@0 | 70 | modrm->mod = b >> 6; /* top 2 bits */ |
michael@0 | 71 | modrm->reg = (b & 56) >> 3; /* middle 3 bits */ |
michael@0 | 72 | modrm->rm = b & 7; /* bottom 3 bits */ |
michael@0 | 73 | } |
michael@0 | 74 | static int ia32_invariant_modrm( unsigned char *in, unsigned char *out, |
michael@0 | 75 | unsigned int mode_16, x86_invariant_op_t *op) { |
michael@0 | 76 | struct modRM_byte modrm; |
michael@0 | 77 | struct SIB_byte sib; |
michael@0 | 78 | unsigned char *c, *cin; |
michael@0 | 79 | unsigned short *s; |
michael@0 | 80 | unsigned int *i; |
michael@0 | 81 | int size = 0; /* modrm byte is already counted */ |
michael@0 | 82 | |
michael@0 | 83 | |
michael@0 | 84 | byte_decode(*in, &modrm); /* get bitfields */ |
michael@0 | 85 | |
michael@0 | 86 | out[0] = in[0]; /* save modrm byte */ |
michael@0 | 87 | cin = &in[1]; |
michael@0 | 88 | c = &out[1]; |
michael@0 | 89 | s = (unsigned short *)&out[1]; |
michael@0 | 90 | i = (unsigned int *)&out[1]; |
michael@0 | 91 | |
michael@0 | 92 | op->type = op_expression; |
michael@0 | 93 | op->flags |= op_pointer; |
michael@0 | 94 | if ( ! mode_16 && modrm.rm == MODRM_RM_SIB && |
michael@0 | 95 | modrm.mod != MODRM_MOD_NOEA ) { |
michael@0 | 96 | size ++; |
michael@0 | 97 | byte_decode(*cin, (struct modRM_byte *)(void*)&sib); |
michael@0 | 98 | |
michael@0 | 99 | out[1] = in[1]; /* save sib byte */ |
michael@0 | 100 | cin = &in[2]; |
michael@0 | 101 | c = &out[2]; |
michael@0 | 102 | s = (unsigned short *)&out[2]; |
michael@0 | 103 | i = (unsigned int *)&out[2]; |
michael@0 | 104 | |
michael@0 | 105 | if ( sib.base == SIB_BASE_EBP && ! modrm.mod ) { |
michael@0 | 106 | /* disp 32 is variant! */ |
michael@0 | 107 | memset( i, X86_WILDCARD_BYTE, 4 ); |
michael@0 | 108 | size += 4; |
michael@0 | 109 | } |
michael@0 | 110 | } |
michael@0 | 111 | |
michael@0 | 112 | if (! modrm.mod && modrm.rm == 101) { |
michael@0 | 113 | if ( mode_16 ) { /* straight RVA in disp */ |
michael@0 | 114 | memset( s, X86_WILDCARD_BYTE, 2 ); |
michael@0 | 115 | size += 2; |
michael@0 | 116 | } else { |
michael@0 | 117 | memset( i, X86_WILDCARD_BYTE, 2 ); |
michael@0 | 118 | size += 4; |
michael@0 | 119 | } |
michael@0 | 120 | } else if (modrm.mod && modrm.mod < 3) { |
michael@0 | 121 | if (modrm.mod == MODRM_MOD_DISP8) { /* offset in disp */ |
michael@0 | 122 | *c = *cin; |
michael@0 | 123 | size += 1; |
michael@0 | 124 | } else if ( mode_16 ) { |
michael@0 | 125 | *s = (* ((unsigned short *) cin)); |
michael@0 | 126 | size += 2; |
michael@0 | 127 | } else { |
michael@0 | 128 | *i = (*((unsigned int *) cin)); |
michael@0 | 129 | size += 4; |
michael@0 | 130 | } |
michael@0 | 131 | } else if ( modrm.mod == 3 ) { |
michael@0 | 132 | op->type = op_register; |
michael@0 | 133 | op->flags &= ~op_pointer; |
michael@0 | 134 | } |
michael@0 | 135 | |
michael@0 | 136 | return (size); |
michael@0 | 137 | } |
michael@0 | 138 | |
michael@0 | 139 | |
michael@0 | 140 | static int ia32_decode_invariant( unsigned char *buf, size_t buf_len, |
michael@0 | 141 | ia32_insn_t *t, unsigned char *out, |
michael@0 | 142 | unsigned int prefixes, x86_invariant_t *inv) { |
michael@0 | 143 | |
michael@0 | 144 | unsigned int addr_size, op_size, mode_16; |
michael@0 | 145 | unsigned int op_flags[3] = { t->dest_flag, t->src_flag, t->aux_flag }; |
michael@0 | 146 | int x, type, bytes = 0, size = 0, modrm = 0; |
michael@0 | 147 | |
michael@0 | 148 | /* set addressing mode */ |
michael@0 | 149 | if (ia32_settings.options & opt_16_bit) { |
michael@0 | 150 | op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2; |
michael@0 | 151 | addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2; |
michael@0 | 152 | mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 0 : 1; |
michael@0 | 153 | } else { |
michael@0 | 154 | op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4; |
michael@0 | 155 | addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4; |
michael@0 | 156 | mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 1 : 0; |
michael@0 | 157 | } |
michael@0 | 158 | |
michael@0 | 159 | for (x = 0; x < 3; x++) { |
michael@0 | 160 | inv->operands[x].access = (enum x86_op_access) |
michael@0 | 161 | OP_PERM(op_flags[x]); |
michael@0 | 162 | inv->operands[x].flags = (enum x86_op_flags) |
michael@0 | 163 | (OP_FLAGS(op_flags[x]) >> 12); |
michael@0 | 164 | |
michael@0 | 165 | switch (op_flags[x] & OPTYPE_MASK) { |
michael@0 | 166 | case OPTYPE_c: |
michael@0 | 167 | size = (op_size == 4) ? 2 : 1; |
michael@0 | 168 | break; |
michael@0 | 169 | case OPTYPE_a: case OPTYPE_v: |
michael@0 | 170 | size = (op_size == 4) ? 4 : 2; |
michael@0 | 171 | break; |
michael@0 | 172 | case OPTYPE_p: |
michael@0 | 173 | size = (op_size == 4) ? 6 : 4; |
michael@0 | 174 | break; |
michael@0 | 175 | case OPTYPE_b: |
michael@0 | 176 | size = 1; |
michael@0 | 177 | break; |
michael@0 | 178 | case OPTYPE_w: |
michael@0 | 179 | size = 2; |
michael@0 | 180 | break; |
michael@0 | 181 | case OPTYPE_d: case OPTYPE_fs: case OPTYPE_fd: |
michael@0 | 182 | case OPTYPE_fe: case OPTYPE_fb: case OPTYPE_fv: |
michael@0 | 183 | case OPTYPE_si: case OPTYPE_fx: |
michael@0 | 184 | size = 4; |
michael@0 | 185 | break; |
michael@0 | 186 | case OPTYPE_s: |
michael@0 | 187 | size = 6; |
michael@0 | 188 | break; |
michael@0 | 189 | case OPTYPE_q: case OPTYPE_pi: |
michael@0 | 190 | size = 8; |
michael@0 | 191 | break; |
michael@0 | 192 | case OPTYPE_dq: case OPTYPE_ps: case OPTYPE_ss: |
michael@0 | 193 | case OPTYPE_pd: case OPTYPE_sd: |
michael@0 | 194 | size = 16; |
michael@0 | 195 | break; |
michael@0 | 196 | case OPTYPE_m: |
michael@0 | 197 | size = (addr_size == 4) ? 4 : 2; |
michael@0 | 198 | break; |
michael@0 | 199 | default: |
michael@0 | 200 | break; |
michael@0 | 201 | } |
michael@0 | 202 | |
michael@0 | 203 | type = op_flags[x] & ADDRMETH_MASK; |
michael@0 | 204 | switch (type) { |
michael@0 | 205 | case ADDRMETH_E: case ADDRMETH_M: case ADDRMETH_Q: |
michael@0 | 206 | case ADDRMETH_R: case ADDRMETH_W: |
michael@0 | 207 | modrm = 1; |
michael@0 | 208 | bytes += ia32_invariant_modrm( buf, out, |
michael@0 | 209 | mode_16, &inv->operands[x]); |
michael@0 | 210 | break; |
michael@0 | 211 | case ADDRMETH_C: case ADDRMETH_D: case ADDRMETH_G: |
michael@0 | 212 | case ADDRMETH_P: case ADDRMETH_S: case ADDRMETH_T: |
michael@0 | 213 | case ADDRMETH_V: |
michael@0 | 214 | inv->operands[x].type = op_register; |
michael@0 | 215 | modrm = 1; |
michael@0 | 216 | break; |
michael@0 | 217 | case ADDRMETH_A: case ADDRMETH_O: |
michael@0 | 218 | /* pad with xF4's */ |
michael@0 | 219 | memset( &out[bytes + modrm], X86_WILDCARD_BYTE, |
michael@0 | 220 | size ); |
michael@0 | 221 | bytes += size; |
michael@0 | 222 | inv->operands[x].type = op_offset; |
michael@0 | 223 | if ( type == ADDRMETH_O ) { |
michael@0 | 224 | inv->operands[x].flags |= op_signed | |
michael@0 | 225 | op_pointer; |
michael@0 | 226 | } |
michael@0 | 227 | break; |
michael@0 | 228 | case ADDRMETH_I: case ADDRMETH_J: |
michael@0 | 229 | /* grab imm value */ |
michael@0 | 230 | if ((op_flags[x] & OPTYPE_MASK) == OPTYPE_v) { |
michael@0 | 231 | /* assume this is an address */ |
michael@0 | 232 | memset( &out[bytes + modrm], |
michael@0 | 233 | X86_WILDCARD_BYTE, size ); |
michael@0 | 234 | } else { |
michael@0 | 235 | memcpy( &out[bytes + modrm], |
michael@0 | 236 | &buf[bytes + modrm], size ); |
michael@0 | 237 | } |
michael@0 | 238 | |
michael@0 | 239 | bytes += size; |
michael@0 | 240 | if ( type == ADDRMETH_J ) { |
michael@0 | 241 | if ( size == 1 ) { |
michael@0 | 242 | inv->operands[x].type = |
michael@0 | 243 | op_relative_near; |
michael@0 | 244 | } else { |
michael@0 | 245 | inv->operands[x].type = |
michael@0 | 246 | op_relative_far; |
michael@0 | 247 | } |
michael@0 | 248 | inv->operands[x].flags |= op_signed; |
michael@0 | 249 | } else { |
michael@0 | 250 | inv->operands[x].type = op_immediate; |
michael@0 | 251 | } |
michael@0 | 252 | break; |
michael@0 | 253 | case ADDRMETH_F: |
michael@0 | 254 | inv->operands[x].type = op_register; |
michael@0 | 255 | break; |
michael@0 | 256 | case ADDRMETH_X: |
michael@0 | 257 | inv->operands[x].flags |= op_signed | |
michael@0 | 258 | op_pointer | op_ds_seg | op_string; |
michael@0 | 259 | break; |
michael@0 | 260 | case ADDRMETH_Y: |
michael@0 | 261 | inv->operands[x].flags |= op_signed | |
michael@0 | 262 | op_pointer | op_es_seg | op_string; |
michael@0 | 263 | break; |
michael@0 | 264 | case ADDRMETH_RR: |
michael@0 | 265 | inv->operands[x].type = op_register; |
michael@0 | 266 | break; |
michael@0 | 267 | case ADDRMETH_II: |
michael@0 | 268 | inv->operands[x].type = op_immediate; |
michael@0 | 269 | break; |
michael@0 | 270 | default: |
michael@0 | 271 | inv->operands[x].type = op_unused; |
michael@0 | 272 | break; |
michael@0 | 273 | } |
michael@0 | 274 | } |
michael@0 | 275 | |
michael@0 | 276 | return (bytes + modrm); |
michael@0 | 277 | } |
michael@0 | 278 | |
michael@0 | 279 | size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len, |
michael@0 | 280 | x86_invariant_t *inv ) { |
michael@0 | 281 | ia32_insn_t *raw_insn = NULL; |
michael@0 | 282 | unsigned int prefixes; |
michael@0 | 283 | unsigned int type; |
michael@0 | 284 | size_t size; |
michael@0 | 285 | |
michael@0 | 286 | /* Perform recursive table lookup starting with main table (0) */ |
michael@0 | 287 | size = ia32_table_lookup( buf, buf_len, 0, &raw_insn, &prefixes ); |
michael@0 | 288 | if ( size == INVALID_INSN || size > buf_len ) { |
michael@0 | 289 | /* TODO: set errno */ |
michael@0 | 290 | return 0; |
michael@0 | 291 | } |
michael@0 | 292 | |
michael@0 | 293 | /* copy opcode bytes to buffer */ |
michael@0 | 294 | memcpy( inv->bytes, buf, size ); |
michael@0 | 295 | |
michael@0 | 296 | /* set mnemonic type and group */ |
michael@0 | 297 | type = raw_insn->mnem_flag & ~INS_FLAG_MASK; |
michael@0 | 298 | inv->group = (enum x86_insn_group) (INS_GROUP(type)) >> 12; |
michael@0 | 299 | inv->type = (enum x86_insn_type) INS_TYPE(type); |
michael@0 | 300 | |
michael@0 | 301 | /* handle operands */ |
michael@0 | 302 | size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn, |
michael@0 | 303 | &buf[size - 1], prefixes, inv ); |
michael@0 | 304 | |
michael@0 | 305 | inv->size = size; |
michael@0 | 306 | |
michael@0 | 307 | return size; /* return size of instruction in bytes */ |
michael@0 | 308 | } |
michael@0 | 309 | |
michael@0 | 310 | size_t ia32_disasm_size( unsigned char *buf, size_t buf_len ) { |
michael@0 | 311 | x86_invariant_t inv = { {0} }; |
michael@0 | 312 | return( ia32_disasm_invariant( buf, buf_len, &inv ) ); |
michael@0 | 313 | } |