Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(310)

Side by Side Diff: src/trusted/validator_ragel/validator_x86_64.rl

Issue 11000033: Move validator_x86_XX.rl out of unreviewed. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be 3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file. 4 * found in the LICENSE file.
5 */ 5 */
6 6
7 /*
8 * This is the core of amd64-mode validator. Please note that this file
9 * combines ragel machine description and C language actions. Please read
10 * validator_internals.html first to understand how the whole thing is built:
11 * it explains how the byte sequences are constructed, what constructs like
12 * “@{}” or “REX_WRX?” mean, etc.
Brad Chen 2012/10/05 16:47:21 Thanks, this is helpful.
13 */
14
7 #include <assert.h> 15 #include <assert.h>
8 #include <errno.h> 16 #include <errno.h>
9 #include <stddef.h> 17 #include <stddef.h>
10 #include <stdio.h> 18 #include <stdio.h>
11 #include <stdlib.h> 19 #include <stdlib.h>
12 #include <string.h> 20 #include <string.h>
13 21
14 #include "native_client/src/trusted/validator_ragel/unreviewed/validator_interna l.h" 22 #include "native_client/src/trusted/validator_ragel/validator_internal.h"
15 23
16 %%{ 24 %%{
17 machine x86_64_validator; 25 machine x86_64_validator;
18 alphtype unsigned char; 26 alphtype unsigned char;
19 variable p current_position; 27 variable p current_position;
20 variable pe end_of_bundle; 28 variable pe end_of_bundle;
21 variable eof end_of_bundle; 29 variable eof end_of_bundle;
22 variable cs current_state; 30 variable cs current_state;
23 31
24 include byte_machine "byte_machines.rl"; 32 include byte_machine "byte_machines.rl";
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 process_2_operands_zero_extends(&restricted_register, 106 process_2_operands_zero_extends(&restricted_register,
99 &instruction_info_collected, rex_prefix, 107 &instruction_info_collected, rex_prefix,
100 operand_states); 108 operand_states);
101 } 109 }
102 110
103 include decode_x86_64 "validator_x86_64_instruction.rl"; 111 include decode_x86_64 "validator_x86_64_instruction.rl";
104 112
105 data16condrep = (data16 | condrep data16 | data16 condrep); 113 data16condrep = (data16 | condrep data16 | data16 condrep);
106 data16rep = (data16 | rep data16 | data16 rep); 114 data16rep = (data16 | rep data16 | data16 rep);
107 115
108 # Special %rbp modifications without required sandboxing 116 # Special %rbp modifications—the ones which don't need a sandboxing.
117 #
118 # Note that there are two different opcodes for “mov”: “mov” with opcode
119 # “0x89” moves from “A” to “B” while “mov” with opcode “0x8b” moves from
120 # “B” to “A”.
109 rbp_modifications = 121 rbp_modifications =
110 (b_0100_10x0 0x89 0xe5) | # mov %rsp,%rbp 122 (b_0100_10x0 0x89 0xe5) | # mov %rsp,%rbp
111 (b_0100_10x0 0x8b 0xec) # | mov %rsp,%rbp 123 (b_0100_10x0 0x8b 0xec) # mov %rsp,%rbp
Brad Chen 2012/10/05 16:47:21 This is much improved with the comments and '|' li
khim 2012/10/15 16:38:57 This was the only case where they were not lined u
Brad Chen 2012/10/16 00:16:55 The way a code review works is I am a proxy for fu
112 #(b_0100_1xx0 0x81 0xe5 any{3} (0x80 .. 0xff)) | # and $XXX,%rbp
113 #(b_0100_1xx0 0x83 0xe5 (0x80 .. 0xff)) # and $XXX,%rbp
114 @process_0_operands; 124 @process_0_operands;
115 125
116 # Special instructions used for %rbp sandboxing 126 # Special instructions used for %rbp sandboxing.
127 #
128 # This is the “second half” of the %rbp sandboxing. Any zero-extending
129 # instruction which stores the data in %ebp can be first part, but unlike
130 # the situation with other “normal” registers you can not just write to
131 # %ebp and continue: such activity MUST restore the status quo immediately
132 # via one of these instructions.
117 rbp_sandboxing = 133 rbp_sandboxing =
118 (b_0100_11x0 0x01 0xfd | # add %r15,%rbp 134 (b_0100_11x0 0x01 0xfd | # add %r15,%rbp
119 b_0100_10x1 0x03 0xef | # add %r15,%rbp 135 b_0100_10x1 0x03 0xef | # add %r15,%rbp
120 0x49 0x8d 0x2c 0x2f | # lea (%r15,%rbp,1),%rbp 136 0x49 0x8d 0x2c 0x2f | # lea (%r15,%rbp,1),%rbp
121 0x4a 0x8d 0x6c 0x3d 0x00) # lea 0x0(%rbp,%r15,1),%rbp 137 0x4a 0x8d 0x6c 0x3d 0x00) # lea 0x0(%rbp,%r15,1),%rbp
138 # “Normal” instructions detect an error when confronted with restricted
139 # register %rbp. These instructions require this state instead.
140 #
141 # Check this precondition and mark the beginning of the instruction as
142 # invalid jump for target.
122 @{ if (restricted_register == REG_RBP) 143 @{ if (restricted_register == REG_RBP)
123 instruction_info_collected |= RESTRICTED_REGISTER_USED; 144 instruction_info_collected |= RESTRICTED_REGISTER_USED;
124 else 145 else
125 instruction_info_collected |= UNRESTRICTED_RBP_PROCESSED; 146 instruction_info_collected |= UNRESTRICTED_RBP_PROCESSED;
126 restricted_register = NO_REG; 147 restricted_register = NO_REG;
127 BitmapClearBit(valid_targets, (instruction_start - data)); 148 MakeInvalidJumpTarget((instruction_start - data), valid_targets);
128 }; 149 };
129 150
130 # Special %rbp modifications without required sandboxing 151 # Special %rsp modifications—the ones which don't need a sandboxing.
152 #
153 # Note that there are two different opcodes for “mov”: “mov” with opcode
154 # “0x89” moves from “A” to “B” while “mov” with opcode “0x8b” moves from
155 # “B” to “A”.
131 rsp_modifications = 156 rsp_modifications =
132 (b_0100_10x0 0x89 0xec) | # mov %rbp,%rsp 157 (b_0100_10x0 0x89 0xec) | # mov %rbp,%rsp
133 (b_0100_10x0 0x8b 0xe5) | # mov %rbp,%rsp 158 (b_0100_10x0 0x8b 0xe5) | # mov %rbp,%rsp
134 #(b_0100_1xx0 0x81 0xe4 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp 159 #(b_0100_1xx0 0x81 0xe4 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp
135 #Superfluous bits are not supported: 160 #Superfluous bits are not supported:
136 # http://code.google.com/p/nativeclient/issues/detail?id=3012 161 # http://code.google.com/p/nativeclient/issues/detail?id=3012
137 (b_0100_1000 0x83 0xe4 (0x80 .. 0xff)) # and $XXX,%rsp 162 (b_0100_1000 0x83 0xe4 (0x80 .. 0xff)) # and $XXX,%rsp
138 @process_0_operands; 163 @process_0_operands;
139 164
140 # Special instructions used for %rbp sandboxing 165 # Special instructions used for %rsp sandboxing.
166 #
167 # This is the “second half” of the %rsp sandboxing. Any zero-extending
168 # instruction which stores the data in %esp can be first part, but unlike
169 # the situation with other “normal” registers you can not just write to
170 # %esp and continue: such activity MUST restore the status quo immediately
171 # via one of these instructions.
141 rsp_sandboxing = 172 rsp_sandboxing =
142 (b_0100_11x0 0x01 0xfc | # add %r15,%rsp 173 (b_0100_11x0 0x01 0xfc | # add %r15,%rsp
143 b_0100_10x1 0x03 0xe7 | # add %r15,%rbp 174 b_0100_10x1 0x03 0xe7 | # add %r15,%rbp
144 0x4a 0x8d 0x24 0x3c) # lea (%rsp,%r15,1),%rsp 175 0x4a 0x8d 0x24 0x3c) # lea (%rsp,%r15,1),%rsp
176 # “Normal” instructions detect an error when confronted with restricted
Brad Chen 2012/10/05 16:47:21 I don't think you mean "detect an error when confr
khim 2012/10/15 16:38:57 I mean normal_instruction ragel machine here, of c
Brad Chen 2012/10/16 00:16:55 As written the comment is unclear. Please clarify.
khim 2013/03/08 17:59:53 Done.
177 # register %rsp. These instructions require this state instead.
178 #
179 # Check this precondition and mark the beginning of the instruction as
180 # invalid jump for target.
145 @{ if (restricted_register == REG_RSP) 181 @{ if (restricted_register == REG_RSP)
146 instruction_info_collected |= RESTRICTED_REGISTER_USED; 182 instruction_info_collected |= RESTRICTED_REGISTER_USED;
147 else 183 else
148 instruction_info_collected |= UNRESTRICTED_RSP_PROCESSED; 184 instruction_info_collected |= UNRESTRICTED_RSP_PROCESSED;
149 restricted_register = NO_REG; 185 restricted_register = NO_REG;
150 BitmapClearBit(valid_targets, (instruction_start - data)); 186 MakeInvalidJumpTarget((instruction_start - data), valid_targets);
151 }; 187 };
152 188
153 # naclcall or nacljmp. Note: first "and $~0x1f, %eXX" is a normal instruction 189 # naclcall or nacljmp. These are three-instruction indirection-jump sequences.
154 # and as such will detect case where %rbp/%rsp is illegally modified. 190 # and $~0x1f, %eXX
191 # and RBASE, %rXX
192 # jmpq *%rXX (or: callq *%rXX)
193 # Note: first "and $~0x1f, %eXX" is a normal instruction and as such will
194 # detect case where %rbp/%rsp is illegally modified when this machine will be
Brad Chen 2012/10/05 16:47:21 Instead of "detect" do you mean "match"?
khim 2012/10/15 16:38:57 No, detect. I mean the following: "0x83 b_11_100_x
Brad Chen 2012/10/16 00:16:55 Let me try to reword my comment to make it clearer
khim 2013/03/08 17:59:53 Tried to reword the meaning to avoid ambiguous wor
195 # combined with normal_instruction machine.
196 #
197 # There are number of variants present which differ by the REX prefix usage:
198 # we need to make sure “%eXX” in “and”, “%rXX” in “add”, and “%eXX” in “jmpq”
199 # or “callq” is the same register and it's much simpler to do if one single
200 # action handles only fixed number of bytes.
201 #
202 # Additional complication arises because x86-64 contains two different “add”
203 # instruction: with “0x01” and “0x03” opcode. They differ in the direction
204 # used: both can add “A” and “B” but one of them stores the result in “A” and
205 # other stores the result in “B” (see AMD/Intel manual for clarification).
206 # Both should be allowed.
207 #
208 # REGISTER USAGE ABBREVIATIONS:
209 # E86: legacy ia32 registers (all eight: %eax to %edi)
210 # R86: 64-bit counterparts for legacy 386 registers (%rax to %rdi)
211 # R64: new amd64 registers (only seven: %r8 to %r14)
212 # E86: 32-bit counterparts for new amd64 registers (%r8d to %r14d)
Brad Chen 2012/10/05 16:47:21 Please list these in this order: E86, R86, E64, R6
khim 2012/10/15 16:38:57 Done.
213 # RBASE: %r15 (used as “base of untrusted world” in NaCl for amd64)
155 naclcall_or_nacljmp = 214 naclcall_or_nacljmp =
156 # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi 215 # This block encodes call and jump superinstructions of the form:
157 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 216 # 0: 83 e_ e0 and $~0x1f,E86
158 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 217 # 3: 4_ 01 f_ add RBASE,R86
159 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff) 218 # 6: ff e_ jmpq *R86
160 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 219 #### INSTRUCTION ONE (three bytes)
161 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | 220 # and $~0x1f, E86
162 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 221 (0x83 b_11_100_xxx 0xe0
163 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) 222 #### INSTRUCTION TWO (three bytes)
164 @{ 223 # add RBASE, R86 (0x01 opcode)
165 instruction_start -= 6; 224 b_0100_11x0 0x01 b_11_111_xxx
166 if (RMFromModRM(instruction_start[1]) != 225 #### INSTRUCTION THREE: call (two bytes plus optional REX prefix)
167 RMFromModRM(instruction_start[5]) || 226 # callq R86
168 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position)) 227 ((REX_WRX? 0xff b_11_010_xxx) |
169 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; 228 #### INSTRUCTION THREE: jmp (two bytes plus optional REX prefix)
170 BitmapClearBit(valid_targets, (instruction_start - data) + 3); 229 # jmpq R86
171 BitmapClearBit(valid_targets, (instruction_start - data) + 6); 230 (REX_WRX? 0xff b_11_100_xxx)))
172 restricted_register = NO_REG; 231 @{
173 } | 232 ProcessNaclCallOrNaclJmp(&instruction_info_collected, &instruction_start,
233 current_position, data, valid_targets,
234 FALSE, FALSE);
235 } |
174 236
175 # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi 237 # This block encodes call and jump superinstructions of the form:
176 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 238 # 0: 83 e_ e0 and $~0x1f,E86
177 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 239 # 3: 4_ 03 f_ add RBASE,R86
178 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff) 240 # 6: ff e_ jmpq *R86
179 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 241 #### INSTRUCTION ONE (three bytes)
180 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | 242 # and $~0x1f, E86
181 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 243 (0x83 b_11_100_xxx 0xe0
182 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) 244 #### INSTRUCTION TWO (three bytes)
183 @{ 245 # add RBASE, R86 (0x03 opcode)
184 instruction_start -= 6; 246 b_0100_10x1 0x03 b_11_xxx_111
185 if (RMFromModRM(instruction_start[1]) != 247 #### INSTRUCTION THREE: call (two bytes plus optional REX prefix)
186 RegFromModRM(instruction_start[5]) || 248 # callq R86
187 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position)) 249 ((REX_WRX? 0xff b_11_010_xxx) |
188 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; 250 #### INSTRUCTION THREE: jmp (two bytes plus optional REX prefix)
189 BitmapClearBit(valid_targets, (instruction_start - data) + 3); 251 # jmpq R86
190 BitmapClearBit(valid_targets, (instruction_start - data) + 6); 252 (REX_WRX? 0xff b_11_100_xxx)))
191 restricted_register = NO_REG; 253 @{
192 } | 254 ProcessNaclCallOrNaclJmp(&instruction_info_collected, &instruction_start,
Brad Chen 2012/10/05 16:47:21 As I mentioned in the file where this procedure is
khim 2012/10/15 16:38:57 Done.
255 current_position, data, valid_targets,
256 FALSE, TRUE);
257 } |
193 258
194 # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi 259 # This block encodes call and jump superinstructions of the form:
195 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 260 # 0: 4_ 83 e_ e0 and $~0x1f,E86
196 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 261 # 4: 4_ 01 f_ add RBASE,R86
197 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff) 262 # 7: ff e_ jmpq *R86
198 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 263 #### INSTRUCTION ONE (four bytes)
199 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | 264 # and $~0x1f, E86
200 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 265 ((REX_RX 0x83 b_11_100_xxx 0xe0
201 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | 266 #### INSTRUCTION TWO (three bytes)
267 # add RBASE, R86 (0x01 opcode)
268 b_0100_11x0 0x01 b_11_111_xxx
269 #### INSTRUCTION THREE: call (two bytes plus optional REX prefix)
270 # callq R86
271 ((REX_WRX? 0xff b_11_010_xxx) |
272 #### INSTRUCTION THREE: jmp (two bytes plus optional REX prefix)
273 # jmpq R86
274 (REX_WRX? 0xff b_11_100_xxx))) |
202 275
203 # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d 276 # This block encodes call and jump superinstructions of the form:
204 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0 277 # 0: 4_ 83 e_ e0 and $~0x1f,E64
205 # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d 278 # 4: 4_ 01 f_ add RBASE,R64
206 b_0100_11x1 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe) 279 # 7: 4_ ff e_ jmpq *R64
207 # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14 280 #### INSTRUCTION ONE (four bytes)
208 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) | 281 # and $~0x1f, E64
209 # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14 282 (b_0100_0xx1 0x83 (b_11_100_xxx - b_11_100_111) 0xe0
210 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6))))) 283 #### INSTRUCTION TWO (three bytes)
211 @{ 284 # add RBASE, R64 (0x01 opcode)
212 instruction_start -= 7; 285 b_0100_11x1 0x01 (b_11_111_xxx - b_11_111_111)
213 if (RMFromModRM(instruction_start[2]) != 286 #### INSTRUCTION THREE: call (three bytes)
214 RMFromModRM(instruction_start[6]) || 287 # callq R64
215 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position)) 288 ((b_0100_xxx1 0xff (b_11_010_xxx - b_11_010_111)) |
216 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; 289 #### INSTRUCTION THREE: jmp (three bytes)
217 BitmapClearBit(valid_targets, (instruction_start - data) + 4); 290 # jmpq R64
218 BitmapClearBit(valid_targets, (instruction_start - data) + 7); 291 (b_0100_xxx1 0xff (b_11_100_xxx - b_11_100_111)))))
219 restricted_register = NO_REG; 292 @{
220 } | 293 ProcessNaclCallOrNaclJmp(&instruction_info_collected, &instruction_start,
294 current_position, data, valid_targets,
295 TRUE, FALSE);
296 } |
221 297
222 # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi 298 # This block encodes call and jump superinstructions of the form:
223 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 299 # 0: 4_ 83 e_ e0 and $~0x1f,E86
224 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 300 # 4: 4_ 03 f_ add RBASE,R86
225 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff) 301 # 7: ff e_ jmpq *R86
226 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 302 #### INSTRUCTION ONE (four bytes)
227 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | 303 # and $~0x1f, E86
228 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 304 ((REX_RX 0x83 b_11_100_xxx 0xe0
229 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | 305 #### INSTRUCTION TWO (three bytes)
306 # add RBASE, R86 (0x03 opcode)
307 b_0100_10x1 0x03 b_11_xxx_111
308 #### INSTRUCTION THREE: call (two bytes plus optional REX prefix)
309 # callq R86
310 ((REX_WRX? 0xff b_11_010_xxx) |
311 #### INSTRUCTION THREE: jmp (two bytes plus optional REX prefix)
312 # jmpq R86
313 (REX_WRX? 0xff b_11_100_xxx))) |
230 314
231 # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d 315 # This block encodes call and jump superinstructions of the form:
232 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0 316 # 0: 4_ 83 e_ e0 and $~0x1f,E64
233 # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d 317 # 4: 4_ 03 f_ add RBASE,R64
234 b_0100_11x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7) 318 # 7: 4_ ff e_ jmpq *R64
235 # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14 319 #### INSTRUCTION ONE (four bytes)
236 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) | 320 # and $~0x1f, E64
237 # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14 321 (b_0100_0xx1 0x83 (b_11_100_xxx - b_11_100_111) 0xe0
238 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6))))) 322 #### INSTRUCTION TWO (three bytes)
239 @{ 323 # add RBASE, R64 (0x03 opcode)
240 instruction_start -= 7; 324 b_0100_11x1 0x03 (b_11_xxx_111 - b_11_111_111)
241 if (RMFromModRM(instruction_start[2]) != 325 #### INSTRUCTION THREE: call (three bytes)
242 RegFromModRM(instruction_start[6]) || 326 # callq R64
243 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position)) 327 ((b_0100_xxx1 0xff (b_11_010_xxx - b_11_010_111)) |
244 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; 328 #### INSTRUCTION THREE: jmp (three bytes)
245 BitmapClearBit(valid_targets, (instruction_start - data) + 4); 329 # jmpq R64
246 BitmapClearBit(valid_targets, (instruction_start - data) + 7); 330 (b_0100_xxx1 0xff (b_11_100_xxx - b_11_100_111)))))
247 restricted_register = NO_REG; 331 @{
248 }; 332 ProcessNaclCallOrNaclJmp(&instruction_info_collected, &instruction_start,
333 current_position, data, valid_targets,
334 TRUE, TRUE);
335 };
249 336
250 # EMMS/SSE2/AVX instructions which have implicit %ds:(%rsi) operand 337 # EMMS/SSE2/AVX instructions which have implicit %ds:(%rsi) operand
251 # maskmovq %mmX,%mmY 338 # maskmovq %mmX,%mmY
252 maskmovq = 339 maskmovq =
253 REX_WRXB? (0x0f 0xf7) 340 REX_WRXB? (0x0f 0xf7)
254 @CPUFeature_EMMX modrm_registers; 341 @CPUFeature_EMMX modrm_registers;
255 # maskmovdqu %xmmX, %xmmY 342 # maskmovdqu %xmmX, %xmmY
256 maskmovdqu = 343 maskmovdqu =
257 0x66 REX_WRXB? (0x0f 0xf7) @not_data16_prefix 344 0x66 REX_WRXB? (0x0f 0xf7) @not_data16_prefix
258 @CPUFeature_SSE2 modrm_registers; 345 @CPUFeature_SSE2 modrm_registers;
(...skipping 23 matching lines...) Expand all
282 # String instructions which use both %ds:(%rsi) and %ds:(%rdi) 369 # String instructions which use both %ds:(%rsi) and %ds:(%rdi)
283 string_instruction_rsi_rdi = 370 string_instruction_rsi_rdi =
284 condrep? 0xa6 | # cmpsb %es:(%rdi),%ds:(%rsi) 371 condrep? 0xa6 | # cmpsb %es:(%rdi),%ds:(%rsi)
285 data16condrep 0xa7 | # cmpsw %es:(%rdi),%ds:(%rsi) 372 data16condrep 0xa7 | # cmpsw %es:(%rdi),%ds:(%rsi)
286 condrep? REXW_NONE? 0xa7 | # cmps[lq] %es:(%rdi),%ds:(%rsi) 373 condrep? REXW_NONE? 0xa7 | # cmps[lq] %es:(%rdi),%ds:(%rsi)
287 374
288 rep? 0xa4 | # movsb %es:(%rdi),%ds:(%rsi) 375 rep? 0xa4 | # movsb %es:(%rdi),%ds:(%rsi)
289 data16rep 0xa5 | # movsw %es:(%rdi),%ds:(%rsi) 376 data16rep 0xa5 | # movsw %es:(%rdi),%ds:(%rsi)
290 rep? REXW_NONE? 0xa5 ; # movs[lq] %es:(%rdi),%ds:(%rsi) 377 rep? REXW_NONE? 0xa5 ; # movs[lq] %es:(%rdi),%ds:(%rsi)
291 378
379 # Superinstruction which handle instructions which require sandboxed %rsi.
380 #
381 # There are two variants which handle spurious REX prefixes.
382 #
383 # Note that both “0x89 0xf6” and “0x8b 0xf6” encode “mov %esi,%esi”:
384 # “mov” with opcode “0x89” moves from “A” to “B” while “mov” with opcode
385 # “0x8b” moves from “B” to “A” but when “A” and “B” happen to denote the
386 # same register there are no functional difference between these opcodes.
292 sandbox_instruction_rsi_no_rdi = 387 sandbox_instruction_rsi_no_rdi =
293 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi 388 (0x89 | 0x8b) 0xf6 # mov %esi,%esi
294 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi 389 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi
295 string_instruction_rsi_no_rdi 390 string_instruction_rsi_no_rdi
296 @{ 391 @{
297 instruction_start -= 6; 392 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data,
298 BitmapClearBit(valid_targets, (instruction_start - data) + 2); 393 valid_targets, FALSE);
299 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
300 restricted_register = NO_REG;
301 } | 394 } |
302 395
303 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi 396 REX_X (0x89 | 0x8b) 0xf6 # mov %esi,%esi
304 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi 397 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi
305 string_instruction_rsi_no_rdi 398 string_instruction_rsi_no_rdi
306 @{ 399 @{
307 instruction_start -= 7; 400 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data,
308 BitmapClearBit(valid_targets, (instruction_start - data) + 3); 401 valid_targets, TRUE);
309 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
310 restricted_register = NO_REG;
311 }; 402 };
312 403
404 # Superinstruction which handle instructions which require sandboxed %rdi.
405 #
406 # There are two variants which handle spurious REX prefixes.
407 #
408 # Note that both “0x89 0xff” and “0x8b 0xff” encode “mov %edi,%edi”:
409 # “mov” with opcode “0x89” moves from “A” to “B” while “mov” with opcode
410 # “0x8b” moves from “B” to “A” but when “A” and “B” happen to denote the
411 # same register there are no functional difference between these opcodes.
313 sandbox_instruction_rdi_no_rsi = 412 sandbox_instruction_rdi_no_rsi =
314 (0x89 | 0x8b) 0xff . # mov %edi,%edi 413 (0x89 | 0x8b) 0xff # mov %edi,%edi
315 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi 414 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi
316 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) 415 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction)
317 @{ 416 @{
318 instruction_start -= 6; 417 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data,
319 BitmapClearBit(valid_targets, (instruction_start - data) + 2); 418 valid_targets, FALSE);
320 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
321 restricted_register = NO_REG;
322 } | 419 } |
323 420
324 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi 421 REX_X (0x89 | 0x8b) 0xff # mov %edi,%edi
325 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi 422 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi
326 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) 423 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction)
327 @{ 424 @{
328 instruction_start -= 7; 425 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data,
329 BitmapClearBit(valid_targets, (instruction_start - data) + 3); 426 valid_targets, TRUE);
330 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
331 restricted_register = NO_REG;
332 }; 427 };
333 428
334 429
335 # String instructions which use both %ds:(%rsi) and %ds:(%rdi) 430 # Superinstruction which handle instructions which require both sandboxed %rsi
431 # and sandboxed %rdi.
432 #
433 # There are four variants which handle spurious REX prefixes.
434 #
435 # Note that both “0x89 0xf6” and “0x8b 0xf6” encode “mov %esi,%esi” while both
436 # “0x89 0xff” and “0x8b 0xff” encode “mov %edi,%edi”: “mov” with opcode “0x89”
437 # moves from “A” to “B” while “mov” with opcode “0x8b” moves from “B” to “A”
438 # but when “A” and “B” happen to denote the same register there are no
439 # functional difference between these opcodes.
440 #
441 # Note: we call SandboxRsiOrRdiMakeInteriorInvalidJumpTargets in actions here
442 # twice because we have two sandboxings here - one for %rsi and one for %rdi.
336 sandbox_instruction_rsi_rdi = 443 sandbox_instruction_rsi_rdi =
337 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi 444 (0x89 | 0x8b) 0xf6 # mov %esi,%esi
338 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi 445 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi
339 (0x89 | 0x8b) 0xff . # mov %edi,%edi 446 (0x89 | 0x8b) 0xff # mov %edi,%edi
340 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi 447 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi
341 string_instruction_rsi_rdi 448 string_instruction_rsi_rdi
342 @{ 449 @{
343 instruction_start -= 12; 450 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data,
344 BitmapClearBit(valid_targets, (instruction_start - data) + 2); 451 valid_targets, FALSE);
345 BitmapClearBit(valid_targets, (instruction_start - data) + 6); 452 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data,
346 BitmapClearBit(valid_targets, (instruction_start - data) + 8); 453 valid_targets, FALSE);
347 BitmapClearBit(valid_targets, (instruction_start - data) + 12);
348 restricted_register = NO_REG;
349 } | 454 } |
350 455
351 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi 456 (0x89 | 0x8b) 0xf6 # mov %esi,%esi
352 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi 457 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi
353 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi 458 REX_X (0x89 | 0x8b) 0xff # mov %edi,%edi
354 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi 459 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi
355 string_instruction_rsi_rdi 460 string_instruction_rsi_rdi
356 @{ 461 @{
357 instruction_start -= 13; 462 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data,
358 BitmapClearBit(valid_targets, (instruction_start - data) + 2); 463 valid_targets, TRUE);
359 BitmapClearBit(valid_targets, (instruction_start - data) + 6); 464 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data,
360 BitmapClearBit(valid_targets, (instruction_start - data) + 9); 465 valid_targets, FALSE);
361 BitmapClearBit(valid_targets, (instruction_start - data) + 13);
362 restricted_register = NO_REG;
363 } | 466 } |
364 467
365 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi 468 REX_X (0x89 | 0x8b) 0xf6 # mov %esi,%esi
366 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi 469 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi
367 (0x89 | 0x8b) 0xff . # mov %edi,%edi 470 (0x89 | 0x8b) 0xff # mov %edi,%edi
368 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi 471 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi
369 string_instruction_rsi_rdi 472 string_instruction_rsi_rdi
370 @{ 473 @{
371 instruction_start -= 13; 474 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data,
372 BitmapClearBit(valid_targets, (instruction_start - data) + 3); 475 valid_targets, FALSE);
373 BitmapClearBit(valid_targets, (instruction_start - data) + 7); 476 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data,
374 BitmapClearBit(valid_targets, (instruction_start - data) + 9); 477 valid_targets, TRUE);
375 BitmapClearBit(valid_targets, (instruction_start - data) + 13);
376 restricted_register = NO_REG;
377 } | 478 } |
378 479
379 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi 480 REX_X (0x89 | 0x8b) 0xf6 # mov %esi,%esi
380 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi 481 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi
381 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi 482 REX_X (0x89 | 0x8b) 0xff # mov %edi,%edi
382 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi 483 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi
383 string_instruction_rsi_rdi 484 string_instruction_rsi_rdi
384 @{ 485 @{
385 instruction_start -= 14; 486 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data,
386 BitmapClearBit(valid_targets, (instruction_start - data) + 3); 487 valid_targets, TRUE);
387 BitmapClearBit(valid_targets, (instruction_start - data) + 7); 488 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data,
388 BitmapClearBit(valid_targets, (instruction_start - data) + 10); 489 valid_targets, TRUE);
389 BitmapClearBit(valid_targets, (instruction_start - data) + 14);
390 restricted_register = NO_REG;
391 }; 490 };
392 491
393 special_instruction = 492 special_instruction =
394 (rbp_modifications | 493 (rbp_modifications |
395 rsp_modifications | 494 rsp_modifications |
396 rbp_sandboxing | 495 rbp_sandboxing |
397 rsp_sandboxing | 496 rsp_sandboxing |
398 naclcall_or_nacljmp | 497 naclcall_or_nacljmp |
399 sandbox_instruction_rsi_no_rdi | 498 sandbox_instruction_rsi_no_rdi |
400 sandbox_instruction_rdi_no_rsi | 499 sandbox_instruction_rdi_no_rsi |
401 sandbox_instruction_rsi_rdi) 500 sandbox_instruction_rsi_rdi)
501 # Mark the instruction as special—currently this information is used only in
502 # tests, but in the future we may use it for dynamic code modification
503 # support.
402 @{ 504 @{
403 instruction_info_collected |= SPECIAL_INSTRUCTION; 505 instruction_info_collected |= SPECIAL_INSTRUCTION;
404 }; 506 };
405 507
406 # Remove special instructions which are only allowed in special cases. 508 # Remove special instructions which are only allowed in special cases.
407 normal_instruction = one_instruction - special_instruction; 509 normal_instruction = one_instruction - special_instruction;
408 510
409 # Check if call is properly aligned 511 # Check if call is properly aligned.
512 #
513 # For direct call we explicitly encode all variations. For indirect call
514 # we accept all the special instructions which ends with indirect call.
410 call_alignment = 515 call_alignment =
411 ((normal_instruction & 516 ((normal_instruction &
412 # Direct call 517 # Direct call
413 ((data16 REX_RXB? 0xe8 rel16) | 518 ((data16 REX_RXB? 0xe8 rel16) |
414 (REX_WRXB? 0xe8 rel32) | 519 (REX_WRXB? 0xe8 rel32) |
415 (data16 REXW_RXB 0xe8 rel32))) | 520 (data16 REXW_RXB 0xe8 rel32))) |
416 (special_instruction & 521 (special_instruction &
417 # Indirect call 522 # Indirect call
418 (any* data16? REX_WRXB? 0xff ((opcode_2 | opcode_3) any* & 523 (any* data16? REX_WRXB? 0xff ((opcode_2 | opcode_3) any* &
419 (modrm_memory | modrm_registers))))) 524 (modrm_memory | modrm_registers)))))
525 # Call instruction must aligned to the end of bundle. Previously this was
526 # strict requirement, today it's just warning to aid with debugging.
420 @{ 527 @{
421 if (((current_position - data) & kBundleMask) != kBundleMask) 528 if (((current_position - data) & kBundleMask) != kBundleMask)
422 instruction_info_collected |= BAD_CALL_ALIGNMENT; 529 instruction_info_collected |= BAD_CALL_ALIGNMENT;
423 }; 530 };
424 531
425 532
426 main := ((call_alignment | normal_instruction | special_instruction) 533 main := ((call_alignment | normal_instruction | special_instruction)
534 # Beginning of the instruction is always valid target for jump. If this
535 # instruction is, in fact, part of the superinstruction then we'll clear
536 # that bit later.
427 >{ 537 >{
428 BitmapSetBit(valid_targets, current_position - data); 538 MakeJumpTargetValid(current_position - data, valid_targets);
429 } 539 }
540 # Here we call the user callback if there are validation errors or if the
541 # CALL_USER_CALLBACK_ON_EACH_INSTRUCTION option is used.
542 #
543 # After that we move instruction_start and clean all the variables which
544 # only used in the processing of a single instruction (prefixes, operand
545 # states and instruction_info_collected).
430 @{ 546 @{
431 if ((instruction_info_collected & 547 if ((instruction_info_collected &
432 (VALIDATION_ERRORS_MASK | BAD_CALL_ALIGNMENT)) || 548 (VALIDATION_ERRORS_MASK | BAD_CALL_ALIGNMENT)) ||
433 (options & CALL_USER_CALLBACK_ON_EACH_INSTRUCTION)) { 549 (options & CALL_USER_CALLBACK_ON_EACH_INSTRUCTION)) {
434 result &= user_callback( 550 result &= user_callback(
435 instruction_start, current_position, 551 instruction_start, current_position,
436 instruction_info_collected | 552 instruction_info_collected |
437 ((restricted_register << RESTRICTED_REGISTER_SHIFT) & 553 ((restricted_register << RESTRICTED_REGISTER_SHIFT) &
438 RESTRICTED_REGISTER_MASK), callback_data); 554 RESTRICTED_REGISTER_MASK), callback_data);
439 } 555 }
440 /* On successful match the instruction start must point to the next byte 556 /* On successful match the instruction start must point to the next byte
441 * to be able to report the new offset as the start of instruction 557 * to be able to report the new offset as the start of instruction
442 * causing error. */ 558 * causing error. */
443 instruction_start = current_position + 1; 559 instruction_start = current_position + 1;
444 instruction_info_collected = 0; 560 instruction_info_collected = 0;
445 SET_REX_PREFIX(FALSE); 561 SET_REX_PREFIX(FALSE);
562 /* Top three bis of VEX2 are inverted: see AMD/Intel manual. */
446 SET_VEX_PREFIX2(0xe0); 563 SET_VEX_PREFIX2(0xe0);
447 SET_VEX_PREFIX3(0x00); 564 SET_VEX_PREFIX3(0x00);
448 operand_states = 0; 565 operand_states = 0;
449 })* 566 })*
450 $err{ 567 $err{
451 result &= user_callback(instruction_start, current_position, 568 result &= user_callback(instruction_start, current_position,
452 UNRECOGNIZED_INSTRUCTION, callback_data); 569 UNRECOGNIZED_INSTRUCTION, callback_data);
453 continue; 570 continue;
454 }; 571 };
455 572
456 }%% 573 }%%
457 574
458 %% write data; 575 %% write data;
459 576
460 Bool ValidateChunkAMD64(const uint8_t *data, size_t size, 577 Bool ValidateChunkAMD64(const uint8_t *data, size_t size,
461 enum validation_options options, 578 enum validation_options options,
462 const NaClCPUFeaturesX86 *cpu_features, 579 const NaClCPUFeaturesX86 *cpu_features,
463 validation_callback_func user_callback, 580 ValidationCallbackFunc user_callback,
464 void *callback_data) { 581 void *callback_data) {
465 bitmap_word valid_targets_small; 582 bitmap_word valid_targets_small;
466 bitmap_word jump_dests_small; 583 bitmap_word jump_dests_small;
467 bitmap_word *valid_targets; 584 bitmap_word *valid_targets;
468 bitmap_word *jump_dests; 585 bitmap_word *jump_dests;
469 const uint8_t *current_position; 586 const uint8_t *current_position;
470 const uint8_t *end_of_bundle; 587 const uint8_t *end_of_bundle;
471 int result = TRUE; 588 int result = TRUE;
472 589
473 CHECK(sizeof valid_targets_small == sizeof jump_dests_small); 590 CHECK(sizeof valid_targets_small == sizeof jump_dests_small);
(...skipping 26 matching lines...) Expand all
500 current_position = end_of_bundle, 617 current_position = end_of_bundle,
501 end_of_bundle = current_position + kBundleSize) { 618 end_of_bundle = current_position + kBundleSize) {
502 /* Start of the instruction being processed. */ 619 /* Start of the instruction being processed. */
503 const uint8_t *instruction_start = current_position; 620 const uint8_t *instruction_start = current_position;
504 int current_state; 621 int current_state;
505 uint32_t instruction_info_collected = 0; 622 uint32_t instruction_info_collected = 0;
506 /* Keeps one byte of information per operand in the current instruction: 623 /* Keeps one byte of information per operand in the current instruction:
507 * 2 bits for register kinds, 624 * 2 bits for register kinds,
508 * 5 bits for register numbers (16 regs plus RIZ). */ 625 * 5 bits for register numbers (16 regs plus RIZ). */
509 uint32_t operand_states = 0; 626 uint32_t operand_states = 0;
510 enum register_name base = NO_REG; 627 enum OperandName base = NO_REG;
511 enum register_name index = NO_REG; 628 enum OperandName index = NO_REG;
512 enum register_name restricted_register = NO_REG; 629 enum OperandName restricted_register = NO_REG;
513 uint8_t rex_prefix = FALSE; 630 uint8_t rex_prefix = FALSE;
514 uint8_t vex_prefix2 = 0xe0; 631 uint8_t vex_prefix2 = 0xe0;
515 uint8_t vex_prefix3 = 0x00; 632 uint8_t vex_prefix3 = 0x00;
516 633
517 %% write init; 634 %% write init;
518 %% write exec; 635 %% write exec;
519 636
520 if (restricted_register == REG_RBP) 637 if (restricted_register == REG_RBP)
521 result &= user_callback(end_of_bundle, end_of_bundle, 638 result &= user_callback(end_of_bundle, end_of_bundle,
522 RESTRICTED_RBP_UNPROCESSED | 639 RESTRICTED_RBP_UNPROCESSED |
(...skipping 10 matching lines...) Expand all
533 user_callback, callback_data); 650 user_callback, callback_data);
534 651
535 /* We only use malloc for a large code sequences */ 652 /* We only use malloc for a large code sequences */
536 if (size > sizeof valid_targets_small) { 653 if (size > sizeof valid_targets_small) {
537 free(jump_dests); 654 free(jump_dests);
538 free(valid_targets); 655 free(valid_targets);
539 } 656 }
540 if (!result) errno = EINVAL; 657 if (!result) errno = EINVAL;
541 return result; 658 return result;
542 } 659 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698