@@ -152,6 +152,18 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> {
152
152
true
153
153
}
154
154
155
+ fn sign_extension ( & self , value : i32 ) -> u64 {
156
+ if self
157
+ . executable
158
+ . get_sbpf_version ( )
159
+ . implicit_sign_extension_of_results ( )
160
+ {
161
+ value as i64 as u64
162
+ } else {
163
+ value as u32 as u64
164
+ }
165
+ }
166
+
155
167
/// Advances the interpreter state by one instruction
156
168
///
157
169
/// Returns false if the program terminated or threw an error.
@@ -245,14 +257,14 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> {
245
257
} ,
246
258
247
259
// BPF_ALU class
248
- ebpf:: ADD32_IMM => self . reg [ dst] = ( self . reg [ dst] as i32 ) . wrapping_add ( insn. imm as i32 ) as u64 ,
249
- ebpf:: ADD32_REG => self . reg [ dst] = ( self . reg [ dst] as i32 ) . wrapping_add ( self . reg [ src] as i32 ) as u64 ,
260
+ ebpf:: ADD32_IMM => self . reg [ dst] = self . sign_extension ( ( self . reg [ dst] as i32 ) . wrapping_add ( insn. imm as i32 ) ) ,
261
+ ebpf:: ADD32_REG => self . reg [ dst] = self . sign_extension ( ( self . reg [ dst] as i32 ) . wrapping_add ( self . reg [ src] as i32 ) ) ,
250
262
ebpf:: SUB32_IMM => if self . executable . get_sbpf_version ( ) . swap_sub_reg_imm_operands ( ) {
251
- self . reg [ dst] = ( insn. imm as i32 ) . wrapping_sub ( self . reg [ dst] as i32 ) as u64
263
+ self . reg [ dst] = self . sign_extension ( ( insn. imm as i32 ) . wrapping_sub ( self . reg [ dst] as i32 ) )
252
264
} else {
253
- self . reg [ dst] = ( self . reg [ dst] as i32 ) . wrapping_sub ( insn. imm as i32 ) as u64
265
+ self . reg [ dst] = self . sign_extension ( ( self . reg [ dst] as i32 ) . wrapping_sub ( insn. imm as i32 ) )
254
266
} ,
255
- ebpf:: SUB32_REG => self . reg [ dst] = ( self . reg [ dst] as i32 ) . wrapping_sub ( self . reg [ src] as i32 ) as u64 ,
267
+ ebpf:: SUB32_REG => self . reg [ dst] = self . sign_extension ( ( self . reg [ dst] as i32 ) . wrapping_sub ( self . reg [ src] as i32 ) ) ,
256
268
ebpf:: MUL32_IMM if !self . executable . get_sbpf_version ( ) . enable_pqr ( ) => self . reg [ dst] = ( self . reg [ dst] as i32 ) . wrapping_mul ( insn. imm as i32 ) as u64 ,
257
269
ebpf:: MUL32_REG if !self . executable . get_sbpf_version ( ) . enable_pqr ( ) => self . reg [ dst] = ( self . reg [ dst] as i32 ) . wrapping_mul ( self . reg [ src] as i32 ) as u64 ,
258
270
ebpf:: DIV32_IMM if !self . executable . get_sbpf_version ( ) . enable_pqr ( ) => self . reg [ dst] = ( self . reg [ dst] as u32 / insn. imm as u32 ) as u64 ,
@@ -277,9 +289,13 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> {
277
289
ebpf:: XOR32_IMM => self . reg [ dst] = ( self . reg [ dst] as u32 ^ insn. imm as u32 ) as u64 ,
278
290
ebpf:: XOR32_REG => self . reg [ dst] = ( self . reg [ dst] as u32 ^ self . reg [ src] as u32 ) as u64 ,
279
291
ebpf:: MOV32_IMM => self . reg [ dst] = insn. imm as u32 as u64 ,
280
- ebpf:: MOV32_REG => self . reg [ dst] = ( self . reg [ src] as u32 ) as u64 ,
281
- ebpf:: ARSH32_IMM => self . reg [ dst] = ( self . reg [ dst] as i32 ) . wrapping_shr ( insn. imm as u32 ) as u64 & ( u32:: MAX as u64 ) ,
282
- ebpf:: ARSH32_REG => self . reg [ dst] = ( self . reg [ dst] as i32 ) . wrapping_shr ( self . reg [ src] as u32 ) as u64 & ( u32:: MAX as u64 ) ,
292
+ ebpf:: MOV32_REG => self . reg [ dst] = if self . executable . get_sbpf_version ( ) . implicit_sign_extension_of_results ( ) {
293
+ self . reg [ src] as u32 as u64
294
+ } else {
295
+ self . reg [ src] as i32 as i64 as u64
296
+ } ,
297
+ ebpf:: ARSH32_IMM => self . reg [ dst] = ( self . reg [ dst] as i32 ) . wrapping_shr ( insn. imm as u32 ) as u32 as u64 ,
298
+ ebpf:: ARSH32_REG => self . reg [ dst] = ( self . reg [ dst] as i32 ) . wrapping_shr ( self . reg [ src] as u32 ) as u32 as u64 ,
283
299
ebpf:: LE if self . executable . get_sbpf_version ( ) . enable_le ( ) => {
284
300
self . reg [ dst] = match insn. imm {
285
301
16 => ( self . reg [ dst] as u16 ) . to_le ( ) as u64 ,
@@ -342,8 +358,8 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> {
342
358
}
343
359
344
360
// BPF_PQR class
345
- ebpf:: LMUL32_IMM if self . executable . get_sbpf_version ( ) . enable_pqr ( ) => self . reg [ dst] = ( self . reg [ dst] as i32 ) . wrapping_mul ( insn. imm as i32 ) as u64 ,
346
- ebpf:: LMUL32_REG if self . executable . get_sbpf_version ( ) . enable_pqr ( ) => self . reg [ dst] = ( self . reg [ dst] as i32 ) . wrapping_mul ( self . reg [ src] as i32 ) as u64 ,
361
+ ebpf:: LMUL32_IMM if self . executable . get_sbpf_version ( ) . enable_pqr ( ) => self . reg [ dst] = ( self . reg [ dst] as u32 ) . wrapping_mul ( insn. imm as u32 ) as u64 ,
362
+ ebpf:: LMUL32_REG if self . executable . get_sbpf_version ( ) . enable_pqr ( ) => self . reg [ dst] = ( self . reg [ dst] as u32 ) . wrapping_mul ( self . reg [ src] as u32 ) as u64 ,
347
363
ebpf:: LMUL64_IMM if self . executable . get_sbpf_version ( ) . enable_pqr ( ) => self . reg [ dst] = self . reg [ dst] . wrapping_mul ( insn. imm as u64 ) ,
348
364
ebpf:: LMUL64_REG if self . executable . get_sbpf_version ( ) . enable_pqr ( ) => self . reg [ dst] = self . reg [ dst] . wrapping_mul ( self . reg [ src] ) ,
349
365
ebpf:: UHMUL64_IMM if self . executable . get_sbpf_version ( ) . enable_pqr ( ) => self . reg [ dst] = ( self . reg [ dst] as u128 ) . wrapping_mul ( insn. imm as u64 as u128 ) . wrapping_shr ( 64 ) as u64 ,
@@ -380,12 +396,12 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> {
380
396
} ,
381
397
ebpf:: SDIV32_IMM if self . executable . get_sbpf_version ( ) . enable_pqr ( ) => {
382
398
throw_error ! ( DivideOverflow ; self , insn. imm, self . reg[ dst] , i32 ) ;
383
- self . reg [ dst] = ( self . reg [ dst] as i32 / insn. imm as i32 ) as u64 ;
399
+ self . reg [ dst] = ( self . reg [ dst] as i32 / insn. imm as i32 ) as u32 as u64 ;
384
400
}
385
401
ebpf:: SDIV32_REG if self . executable . get_sbpf_version ( ) . enable_pqr ( ) => {
386
402
throw_error ! ( DivideByZero ; self , self . reg[ src] , i32 ) ;
387
403
throw_error ! ( DivideOverflow ; self , self . reg[ src] , self . reg[ dst] , i32 ) ;
388
- self . reg [ dst] = ( self . reg [ dst] as i32 / self . reg [ src] as i32 ) as u64 ;
404
+ self . reg [ dst] = ( self . reg [ dst] as i32 / self . reg [ src] as i32 ) as u32 as u64 ;
389
405
} ,
390
406
ebpf:: SDIV64_IMM if self . executable . get_sbpf_version ( ) . enable_pqr ( ) => {
391
407
throw_error ! ( DivideOverflow ; self , insn. imm, self . reg[ dst] , i64 ) ;
@@ -398,12 +414,12 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> {
398
414
} ,
399
415
ebpf:: SREM32_IMM if self . executable . get_sbpf_version ( ) . enable_pqr ( ) => {
400
416
throw_error ! ( DivideOverflow ; self , insn. imm, self . reg[ dst] , i32 ) ;
401
- self . reg [ dst] = ( self . reg [ dst] as i32 % insn. imm as i32 ) as u64 ;
417
+ self . reg [ dst] = ( self . reg [ dst] as i32 % insn. imm as i32 ) as u32 as u64 ;
402
418
}
403
419
ebpf:: SREM32_REG if self . executable . get_sbpf_version ( ) . enable_pqr ( ) => {
404
420
throw_error ! ( DivideByZero ; self , self . reg[ src] , i32 ) ;
405
421
throw_error ! ( DivideOverflow ; self , self . reg[ src] , self . reg[ dst] , i32 ) ;
406
- self . reg [ dst] = ( self . reg [ dst] as i32 % self . reg [ src] as i32 ) as u64 ;
422
+ self . reg [ dst] = ( self . reg [ dst] as i32 % self . reg [ src] as i32 ) as u32 as u64 ;
407
423
} ,
408
424
ebpf:: SREM64_IMM if self . executable . get_sbpf_version ( ) . enable_pqr ( ) => {
409
425
throw_error ! ( DivideOverflow ; self , insn. imm, self . reg[ dst] , i64 ) ;
0 commit comments