mirror of
				https://github.com/bytecodealliance/wasm-micro-runtime.git
				synced 2025-10-27 03:11:18 +00:00 
			
		
		
		
	 37d7439ef9
			
		
	
	
		37d7439ef9
		
			
		
	
	
	
	
		
			
			There's probably a number of other places where the bh_leb_read could be used (e.g. aot loader) but I'm making the change as small as possible. Further refactoring can be done later.
		
			
				
	
	
		
			77 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			77 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2019 Intel Corporation.  All rights reserved.
 | |
|  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
|  */
 | |
| 
 | |
| #include "bh_leb128.h"
 | |
| 
 | |
| bh_leb_read_status_t
 | |
| bh_leb_read(const uint8 *buf, const uint8 *buf_end, uint32 maxbits, bool sign,
 | |
|             uint64 *p_result, size_t *p_offset)
 | |
| {
 | |
|     uint64 result = 0;
 | |
|     uint32 shift = 0;
 | |
|     uint32 offset = 0, bcnt = 0;
 | |
|     uint64 byte;
 | |
| 
 | |
|     while (true) {
 | |
|         /* uN or SN must not exceed ceil(N/7) bytes */
 | |
|         if (bcnt + 1 > (maxbits + 6) / 7) {
 | |
|             return BH_LEB_READ_TOO_LONG;
 | |
|         }
 | |
| 
 | |
|         if ((uintptr_t)buf + offset + 1 < (uintptr_t)buf
 | |
|             || (uintptr_t)buf + offset + 1 > (uintptr_t)buf_end) {
 | |
|             return BH_LEB_READ_UNEXPECTED_END;
 | |
|         }
 | |
|         byte = buf[offset];
 | |
|         offset += 1;
 | |
|         result |= ((byte & 0x7f) << shift);
 | |
|         shift += 7;
 | |
|         bcnt += 1;
 | |
|         if ((byte & 0x80) == 0) {
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (!sign && maxbits == 32 && shift >= maxbits) {
 | |
|         /* The top bits set represent values > 32 bits */
 | |
|         if (((uint8)byte) & 0xf0)
 | |
|             return BH_LEB_READ_OVERFLOW;
 | |
|     }
 | |
|     else if (sign && maxbits == 32) {
 | |
|         if (shift < maxbits) {
 | |
|             /* Sign extend, second-highest bit is the sign bit */
 | |
|             if ((uint8)byte & 0x40)
 | |
|                 result |= (~((uint64)0)) << shift;
 | |
|         }
 | |
|         else {
 | |
|             /* The top bits should be a sign-extension of the sign bit */
 | |
|             bool sign_bit_set = ((uint8)byte) & 0x8;
 | |
|             int top_bits = ((uint8)byte) & 0xf0;
 | |
|             if ((sign_bit_set && top_bits != 0x70)
 | |
|                 || (!sign_bit_set && top_bits != 0))
 | |
|                 return BH_LEB_READ_OVERFLOW;
 | |
|         }
 | |
|     }
 | |
|     else if (sign && maxbits == 64) {
 | |
|         if (shift < maxbits) {
 | |
|             /* Sign extend, second-highest bit is the sign bit */
 | |
|             if ((uint8)byte & 0x40)
 | |
|                 result |= (~((uint64)0)) << shift;
 | |
|         }
 | |
|         else {
 | |
|             /* The top bits should be a sign-extension of the sign bit */
 | |
|             bool sign_bit_set = ((uint8)byte) & 0x1;
 | |
|             int top_bits = ((uint8)byte) & 0xfe;
 | |
| 
 | |
|             if ((sign_bit_set && top_bits != 0x7e)
 | |
|                 || (!sign_bit_set && top_bits != 0))
 | |
|                 return BH_LEB_READ_OVERFLOW;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     *p_offset = offset;
 | |
|     *p_result = result;
 | |
|     return BH_LEB_READ_SUCCESS;
 | |
| } |