diff --git a/jbmc/src/java_bytecode/java_bytecode_parser.cpp b/jbmc/src/java_bytecode/java_bytecode_parser.cpp index e036b06bdc4..2fe7ccafbf7 100644 --- a/jbmc/src/java_bytecode/java_bytecode_parser.cpp +++ b/jbmc/src/java_bytecode/java_bytecode_parser.cpp @@ -132,9 +132,19 @@ class java_bytecode_parsert final : public parsert T read() { static_assert( - std::is_unsigned<T>::value, "T should be an unsigned integer"); + std::is_unsigned<T>::value || std::is_signed<T>::value, + "T should be a signed or unsigned integer"); const constexpr size_t bytes = sizeof(T); - u8 result = 0; + if(bytes == 1) + { + if(!*in) + { + log.error() << "unexpected end of bytecode file" << messaget::eom; + throw 0; + } + return static_cast<T>(in->get()); + } + T result = 0; for(size_t i = 0; i < bytes; i++) { if(!*in) @@ -145,7 +155,7 @@ class java_bytecode_parsert final : public parsert result <<= 8u; result |= static_cast<u1>(in->get()); } - return narrow_cast<T>(result); + return result; } void store_unknown_method_handle(size_t bootstrap_method_index); @@ -695,15 +705,15 @@ void java_bytecode_parsert::rconstant_pool() break; case CONSTANT_Utf8: - { - const u2 bytes = read<u2>(); - std::string s; - s.resize(bytes); - for(auto &ch : s) - ch = read<u1>(); - it->s = s; // Add to string table - } + { + const u2 bytes = read<u2>(); + std::string s; + s.resize(bytes); + for(auto &ch : s) + ch = read<std::string::value_type>(); + it->s = s; // Add to string table break; + } case CONSTANT_MethodHandle: it->ref1 = read<u1>(); @@ -941,34 +951,34 @@ void java_bytecode_parsert::rbytecode(std::vector<instructiont> &instructions) break; case 'b': // a signed byte - { - const s1 c = read<u1>(); - instruction.args.push_back(from_integer(c, signedbv_typet(8))); - } + { + const s1 c = read<s1>(); + instruction.args.push_back(from_integer(c, signedbv_typet(8))); address+=1; break; + } case 'o': // two byte branch offset, signed - { - const s2 offset = read<u2>(); - // By converting the signed offset into an absolute address (by adding - // the current address) the number represented becomes unsigned. - instruction.args.push_back( - from_integer(address+offset, unsignedbv_typet(16))); - } + { + const s2 offset = read<s2>(); + // By converting the signed offset into an absolute address (by adding + // the current address) the number represented becomes unsigned. + instruction.args.push_back( + from_integer(address + offset, unsignedbv_typet(16))); address+=2; break; + } case 'O': // four byte branch offset, signed - { - const s4 offset = read<u4>(); - // By converting the signed offset into an absolute address (by adding - // the current address) the number represented becomes unsigned. - instruction.args.push_back( - from_integer(address+offset, unsignedbv_typet(32))); - } + { + const s4 offset = read<s4>(); + // By converting the signed offset into an absolute address (by adding + // the current address) the number represented becomes unsigned. + instruction.args.push_back( + from_integer(address + offset, unsignedbv_typet(32))); address+=4; break; + } case 'v': // local variable index (one byte) { @@ -994,7 +1004,7 @@ void java_bytecode_parsert::rbytecode(std::vector<instructiont> &instructions) { const u2 v = read<u2>(); instruction.args.push_back(from_integer(v, unsignedbv_typet(16))); - const s2 c = read<u2>(); + const s2 c = read<s2>(); instruction.args.push_back(from_integer(c, signedbv_typet(16))); address+=4; } @@ -1002,7 +1012,7 @@ void java_bytecode_parsert::rbytecode(std::vector<instructiont> &instructions) { const u1 v = read<u1>(); instruction.args.push_back(from_integer(v, unsignedbv_typet(8))); - const s1 c = read<u1>(); + const s1 c = read<s1>(); instruction.args.push_back(from_integer(c, signedbv_typet(8))); address+=2; } @@ -1032,7 +1042,7 @@ void java_bytecode_parsert::rbytecode(std::vector<instructiont> &instructions) } // now default value - const s4 default_value = read<u4>(); + const s4 default_value = read<s4>(); // By converting the signed offset into an absolute address (by adding // the current address) the number represented becomes unsigned. instruction.args.push_back( @@ -1045,8 +1055,8 @@ void java_bytecode_parsert::rbytecode(std::vector<instructiont> &instructions) for(std::size_t i=0; i<npairs; i++) { - const s4 match = read<u4>(); - const s4 offset = read<u4>(); + const s4 match = read<s4>(); + const s4 offset = read<s4>(); instruction.args.push_back( from_integer(match, signedbv_typet(32))); // By converting the signed offset into an absolute address (by adding @@ -1070,23 +1080,23 @@ void java_bytecode_parsert::rbytecode(std::vector<instructiont> &instructions) } // now default value - const s4 default_value = read<u4>(); + const s4 default_value = read<s4>(); instruction.args.push_back( from_integer(base_offset+default_value, signedbv_typet(32))); address+=4; // now low value - const s4 low_value = read<u4>(); + const s4 low_value = read<s4>(); address+=4; // now high value - const s4 high_value = read<u4>(); + const s4 high_value = read<s4>(); address+=4; // there are high-low+1 offsets, and they are signed for(s4 i=low_value; i<=high_value; i++) { - s4 offset = read<u4>(); + s4 offset = read<s4>(); instruction.args.push_back(from_integer(i, signedbv_typet(32))); // By converting the signed offset into an absolute address (by adding // the current address) the number represented becomes unsigned. @@ -1130,8 +1140,8 @@ void java_bytecode_parsert::rbytecode(std::vector<instructiont> &instructions) case 's': // a signed short { - const s2 s = read<u2>(); - instruction.args.push_back(from_integer(s, signedbv_typet(16))); + const s2 s = read<s2>(); + instruction.args.push_back(from_integer(s, signedbv_typet(16))); } address+=2; break;