diff verifier/Pass1.cpp patched/verifier/Pass1.cpp 175c175 < /* 0x84 OP_IINC */ { 3, 0 }, --- > /* 0x84 OP_IINC */ { 3, PI_CANWIDE }, 359c359 < if( instr >= m_code_length || props.isOperand(instr) ) { --- > if( instr > m_code_length || props.isOperand(instr) ) { 366c366,368 < props.setMultiway(instr); --- > if( !dead_code_parsing ) { > props.setMultiway(instr); > } 426,427c428,433 < // it is not an if* - go to jump target < instr = target; --- > //TODO: though the spec does not require to check the dead code for correctness > //RI seems to check it and some Harmony negative tests have broken dead code > > dead_code_stack.push(instr+instr_len); > > instr = target; // it is not an if* - go to jump target 435a442,443 > dead_code_stack.push(instr+instr_len); > 467a476,479 > if(dead_code_parsing) { > return VER_OK; > } > diff verifier/Pass2.cpp patched/verifier/Pass2.cpp 448c448 < if( !tpool.cpool_get_array(cp_idx, &arrayref) ) return error(VER_ErrorConstantPool, "incorrect constantpool entry"); --- > if( !tpool.cpool_get_array(cp_idx, &arrayref) ) return error(VER_ErrorConstantPool, "incorrect type for anewarray"); 478c478 < byte local_idx = m_bytecode[instr+1]; --- > int local_idx = wide ? read_int16(m_bytecode + instr + 2) : m_bytecode[instr + 1]; 691c691 < byte local_idx = m_bytecode[instr+1]; --- > int local_idx = wide ? read_int16(m_bytecode + instr + 2) : m_bytecode[instr + 1]; 969c969 < byte local_idx = m_bytecode[instr+1]; --- > int local_idx = wide ? read_int16(m_bytecode + instr + 2) : m_bytecode[instr + 1]; 1171c1171 < byte local_idx = m_bytecode[instr+1]; --- > int local_idx = wide ? read_int16(m_bytecode + instr + 2) : m_bytecode[instr + 1]; 1267a1268,1270 > //check stack > if( !workmap_can_push(1) ) return error(VER_ErrorDataFlow, "operand stack overflow"); > 1278a1282,1284 > //check stack > if( !workmap_can_push(1) ) return error(VER_ErrorDataFlow, "operand stack overflow"); > 1289a1296,1298 > //check stack > if( !workmap_can_push(2) ) return error(VER_ErrorDataFlow, "operand stack overflow"); > 1331c1340 < byte local_idx = m_bytecode[instr+1]; --- > int local_idx = wide ? read_int16(m_bytecode + instr + 2) : m_bytecode[instr + 1]; 1358a1368,1370 > if( !dims ) { > return error(VER_ErrorConstantPool, "incorrect format of multianewarray"); > } 1374c1386,1388 < if( !tpool.cpool_get_class(cp_idx, &arrayref) ) return error(VER_ErrorConstantPool, "incorrect constantpool entry"); --- > if( !tpool.cpool_get_class(cp_idx, &arrayref, (int)dims) ) { > return error(VER_ErrorConstantPool, "incorrect type for multianewarray"); > } 1389,1390c1403,1406 < //if( !tpool.cpool_get_class(cp_idx, &new_type) ) return VER_ErrorConstantPool; < if( !tpool.cpool_get_class(cp_idx, 0) ) return error(VER_ErrorConstantPool, "incorrect constantpool entry"); --- > //if( !tpool.cpool_get_class(cp_idx, &new_type, 0xFFFFFFFF) ) return VER_ErrorConstantPool; > if( !tpool.cpool_get_class(cp_idx, 0, -1) ) { > return error(VER_ErrorConstantPool, "incorrect constantpool entry for new"); > } 1446a1463,1466 > > if( m_is_constructor && !workmap_expect_strict(workmap->elements[m_max_locals], tpool.sm_get_const_this()) ) { > return error(VER_ErrorIncompatibleArgument, "has not called constructor of super class"); > } 1527c1547,1549 < if( !tpool.cpool_get_field(cp_idx, &expected_ref, &expected_val) ) return error(VER_ErrorUnknown, "incorrect constantpool entry"); --- > if( !tpool.cpool_get_field(cp_idx, &expected_ref, &expected_val) ) { > return error(VER_ErrorUnknown, "incorrect constantpool entry"); > } 1531a1554,1557 > if (!workmap_can_pop(1)) { > return error(VER_ErrorUnknown, "unable to pop from the empty stack"); > } > 1575a1602,1616 > if( opcode == OP_INVOKEINTERFACE ) { > //TODO: is verifier the right place for this check? > //check 'count' value for invokeinterface instruction > byte count = m_bytecode[instr + 3]; > byte fourth = m_bytecode[instr + 4]; > if( count != args_sz + 1 || fourth ) { > return error(VER_ErrorUnknown, "incorrect invokeinterface instruction"); > } > } > > if( args_sz > 255 || args_sz > 254 && opcode != OP_INVOKESTATIC ) { > //TODO: is verifier the right place for this check? > return error(VER_ErrorUnknown, "too many arguments for the method"); > } > 1593c1634,1639 < if( opcode == OP_INVOKESPECIAL && tpool.cpool_method_is_constructor_call(name_idx) ) { --- > if( tpool.cpool_method_is_constructor_call(name_idx) ) { > if( opcode != OP_INVOKESPECIAL ) { > //TODO: is verifier the right place for this check? > return error(VER_ErrorUnknown, "constructor must be called by invokespecial"); > } > 1615,1616d1660 < < //TODO: JSRs: check that it works in subroutines 1625,1626c1669,1670 < //replace all uninit values on stack & locals with init value < for( unsigned i = 0; i < workmap->depth + m_max_locals; i++ ) { --- > //replace all uninit values on stack & locals & possibly "constructor called flag" with init value > for( unsigned i = 0; i < + m_stack_start + workmap->depth; i++ ) { 1633c1677 < if( i < m_max_locals ) { --- > if( i < m_stack_start ) { 1634a1679 > 1635a1681 > assert(wm_el.isJsrModified()); 1646c1692 < //check that objectref is exactly nessesary class --- > //check that objectref is exactly necessary class 1648,1653c1694,1700 < if( tpool.sm_get_const_this() != tpool.sm_get_const_object() ) { < if( expected_ref != tpool.sm_get_const_this() && < expected_ref != tpool.sm_get_const_super() ) < { < return error(VER_ErrorUnknown, "incorrect uninitialized type"); < } --- > assert(m_is_constructor); > assert(tpool.sm_get_const_this() != tpool.sm_get_const_object()); > > if( expected_ref != tpool.sm_get_const_this() && > expected_ref != tpool.sm_get_const_super() ) > { > return error(VER_ErrorUnknown, "incorrect uninitialized type"); 1654a1702 > 1658,1669d1705 < < //update flags < if( uninit_value == SM_THISUNINIT ) { < //TODO: JSRs: verify it works in subroutines < assert( workmap->flags ); < < if( workmap->flags & THIS_INIT ) { < //constructor is invoked twice < return error(VER_ErrorUnknown, "constructor is invoked twice"); < } < workmap->flags |= THIS_INIT; < } 1683d1718 < 1688c1723,1724 < Address target = instr + (wide ? read_int32(m_bytecode + instr + 1) : read_int16(m_bytecode + instr + 1)); --- > Address target = instr + (opcode == OP_JSR_W ? > read_int32(m_bytecode + instr + 1) : read_int16(m_bytecode + instr + 1)); 1693,1700d1728 < //check if the retaddr already presents on the stack < //TODO: are the recursions illegal? < for( unsigned i = 0; i < m_max_locals + workmap->depth; i++ ) { < if( workmap->elements[i].getAnyPossibleValue() == retaddr ) { < return error(VER_ErrorDataFlow, "recursive subroutine"); < } < } < 1725,1726c1753 < //TODO: are the recursions illegal? < for( unsigned i = 0; i < workmap->depth + m_max_locals; i++ ) { --- > for( unsigned i = 0; i < m_stack_start + workmap->depth; i++ ) { 1735c1762 < //store types --- > //actually is not a ret address: it's an address of subroutine's start 1776,1779c1803,1805 < Verifier_Result vf_Context_t::ResumeJsr(Address jsr) { < OpCode opcode = (OpCode)m_bytecode[jsr]; < ParseInfo &pi = instr_get_parse_info(opcode); < Address subr = instr_get_jump_target(pi, m_bytecode, jsr); --- > Verifier_Result vf_Context_t::SubroutineDone(Address subr) { > SubroutineData *subrdata = props.getInstrProps(subr)->next->getSubrData(m_max_stack + m_stack_start); > subrdata->subrDataflowed = 1; 1780a1807,1810 > if( !subrdata->retCount ) { > //no ret from subroutine -- dead code follows > return VER_OK; > } 1782c1812 < SubroutineData *subrdata = props.getInstrProps(subr)->next->getSubrData(m_max_stack + m_max_locals); --- > Address jsr = subrdata->caller; 1783a1814,1815 > OpCode opcode = (OpCode)m_bytecode[jsr]; > ParseInfo &pi = instr_get_parse_info(opcode); 1787c1819 < //note that in ResumeJsrDataflow unlike StartLinearDataflow we get workmap from stackmap --- > //note that in SubroutineDone unlike StartLinearDataflow we get workmap from stackmap 1801,1802c1833,1834 < Address instr = jsr + (opcode == OP_WIDE ? 5 : 3); < assert(opcode == OP_JSR || opcode == OP_WIDE && m_bytecode[jsr+1] == OP_JSR); --- > Address instr = jsr + (opcode == OP_JSR_W ? 5 : 3); > assert(opcode == OP_JSR || opcode == OP_JSR_W); 1809,1825d1840 < Verifier_Result vf_Context_t::SubroutineDone(Address subr) { < SubroutineData *subrdata = props.getInstrProps(subr)->next->getSubrData(m_max_stack + m_max_locals); < subrdata->subrDataflowed = 1; < if( !subrdata->retCount ) { < //no ret from subroutine -- dead code follows < return VER_OK; < } < < SubrCaller* next = subrdata->callers; < < while( next ) { < stack.push(next->caller); < stack.push(MARK_RESUME_JSR); < next = next->next; < } < return VER_OK; < } 1848,1849d1862 < assert(workmap->flags); < 1871,1873c1884,1886 < //TODO: need to test commented out optimization < if( props.isMultiway(target) /*&& (!instr_direct(pi) || props.isDataflowPassed(target))*/ ) { < //new_generic_vector_constraint(target); --- > if( props.isMultiway(target) || instr_is_jsr(opcode) ) { > //TODO: need to test commented out optimization > //&& (!instr_direct(pi) || props.isDataflowPassed(target)) 1890,1899d1902 < if( !props.isMultiway(target) ) { < //if* with no stackmap at branch < storeWorkmapCopy(target); < assert( !props.isDataflowPassed(target) ); < < stack.push(target); < < instr += instr_len; < continue; < } 1906,1907c1909,1916 < for( unsigned i = 0; i < m_max_locals; i++ ) { < target_pro->stackmap.elements[i].clearJsrModified(); --- > //for each local and stack (except just added retaddr) replace other retaddresses > //by SM_BOGUS to avoid ret from non-top subroutine on stack > assert(workmap->depth == target_pro->stackmap.depth); > for( unsigned i = 0; i < m_stack_start + workmap->depth - 1; i++ ) { > StackmapElement &el = target_pro->stackmap.elements[i]; > if( el.getAnyIncomingValue().isRetAddr() ) { > el.newIncomingType(&mem, SM_BOGUS); > } 1909a1919,1922 > for( unsigned i = 0; i < m_stack_start; i++ ) { > StackmapElement &el = target_pro->stackmap.elements[i]; > el.clearJsrModified(); > } 1918c1931 < SubroutineData *subrdata = retpro->getSubrData(m_max_locals+m_max_stack); --- > SubroutineData *subrdata = retpro->getSubrData(m_stack_start+m_max_stack); 1928c1941 < subrdata->toWaitList(&mem, instr); --- > subrdata->caller = instr; 1930,1932c1943,1944 < //need to do some finalizing stuff < stack.push(target); < stack.push(MARK_SUBROUTINE_DONE); --- > //need to postpone some finalizing stuff > stack.xPush(target, MARK_SUBROUTINE_DONE); 1935c1947,1948 < stack.push(target); --- > stack.xPush(target); > 1938c1951 < SubroutineData *subrdata = target_pro->next->getSubrData(m_max_locals+m_max_stack); --- > SubroutineData *subrdata = target_pro->next->getSubrData(m_stack_start+m_max_stack); 1941,1943c1954,1955 < //need to return to that JSR instr later, when finish subroutine processing < subrdata->toWaitList(&mem, instr); < return VER_OK; --- > //recursive call? > return error(VER_ErrorDataFlow, "recursive subroutine"); 1957a1970,1975 > if( !props.isMultiway(target) ) { > //if* with no stackmap at branch > storeWorkmapCopy(target); > assert( !props.isDataflowPassed(target) ); > } > 1959c1977 < stack.push(target); --- > stack.xPush(target); 2034c2052 < stack.push(handler_pc); --- > stack.xPush(handler_pc); 2047,2055c2065,2066 < if( handler->flags ) { < //been there < if( handler->flags != workmap->flags ) return error(VER_ErrorDataFlow, "initialized states differ"); < } else { < handler->flags = workmap->flags; < } < < //merge local variables < for( unsigned i = 0; i < m_max_locals; i++ ) { --- > //merge non-stack variables > for( unsigned i = 0; i < m_stack_start; i++ ) { 2071c2082 < for( unsigned i = 0; i < m_max_locals; i++ ) { --- > for( unsigned i = 0; i < m_stack_start; i++ ) { 2103,2107c2114,2115 < //checked in dataflow_handlers < assert( handler->flags == workmap->flags ); < < //merge local variables < for( unsigned i = 0; i < m_max_locals; i++ ) { --- > //merge non-stack variables > for( unsigned i = 0; i < m_stack_start; i++ ) { 2198,2201c2206,2215 < while( !stack.is_empty() ) { < Verifier_Result tcr = parse(stack.pop()); < if( tcr != VER_OK ) { < return tcr; --- > //we have different slightly rules for processing dead and live code > //e.g. it's not a problem if dead code runs out of the method > //but we still have to verify it for corrupted instructions to follow RI > dead_code_parsing = 0; > do { > while( !stack.is_empty() ) { > Verifier_Result tcr = parse(stack.pop()); > if( tcr != VER_OK ) { > return tcr; > } 2203c2217,2228 < } --- > > dead_code_parsing = 1; > > while( !dead_code_stack.is_empty() ) { > Verifier_Result tcr = parse(dead_code_stack.pop()); > if( tcr != VER_OK ) { > return tcr; > } > } > } while (!stack.is_empty()); > > 2210c2235,2237 < assert(end_pc == m_code_length || !props.isOperand(end_pc) ); --- > if( end_pc < m_code_length && props.isOperand(end_pc) || props.isOperand(start_pc) ) { > return error(VER_ErrorCodeEnd, "start_pc or end_pc are at the middle of an instruction"); > } 2229a2257,2260 > stack.xPush(0); > while( !stack.is_empty() ) { > Address next; > short mark; 2231,2245c2262 < //find unused Adresses to define stack mark "constants" < if( m_code_length < 0xFFF0 ) { < MARK_SUBROUTINE_DONE = 0xFFF1; < MARK_RESUME_JSR = 0xFFF2; < } else { < int i = 0; < while( !props.isOperand(i) ) { < i++; < } < MARK_SUBROUTINE_DONE = i; < while( !props.isOperand(i) ) { < i++; < } < MARK_RESUME_JSR = i; < } --- > stack.xPop(&next, &mark); 2247,2254c2264 < stack.push(0); < while( !stack.is_empty() ) { < Address next = stack.pop(); < if( next == MARK_SUBROUTINE_DONE ) { < tcr = SubroutineDone(stack.pop()); < } else if( next == MARK_RESUME_JSR ) { < tcr = ResumeJsr(stack.pop()); < } else { --- > if( !mark ) { 2255a2266,2268 > } else { > assert(mark == MARK_SUBROUTINE_DONE); > tcr = SubroutineDone(next); 2276,2283c2289 < if( target->flags || target->depth ) { < //been there < if( target->flags != workmap->flags ) return error(VER_ErrorDataFlow, "initialized states differ"); < if( target->depth != workmap->depth ) return error(VER_ErrorStackDeep, "stack depth does not match"); < } else { < target->flags = workmap->flags; < target->depth = workmap->depth; < } --- > if( target->depth != workmap->depth ) return error(VER_ErrorStackDeep, "stack depth does not match"); 2285,2286c2291,2292 < //merge local and stack variables < for( unsigned i = 0; i < m_max_locals + workmap->depth; i++ ) { --- > //merge all variables > for( unsigned i = 0; i < m_stack_start + workmap->depth; i++ ) { 2299,2300d2304 < Verifier_Result tcr; < 2305c2309 < SubroutineData *subrdata = outpro->getSubrData(m_max_locals + m_max_stack); --- > SubroutineData *subrdata = outpro->getSubrData(m_stack_start + m_max_stack); 2311c2315 < tc_memcpy(outpro->getWorkmap(), workmap, sizeof(WorkmapHead) + sizeof(WorkmapElement) * (m_max_locals + workmap->depth)); --- > tc_memcpy(outpro->getWorkmap(), workmap, sizeof(WorkmapHead) + sizeof(WorkmapElement) * (m_stack_start + workmap->depth)); 2315,2362c2319 < StackmapHead *outcoming = outpro->getStackmap(); < < assert(outcoming->flags || outcoming->depth); //been there < < if( outcoming->flags != workmap->flags ) return error(VER_ErrorDataFlow, "initialized states differ"); < if( outcoming->depth != workmap->depth ) return error(VER_ErrorStackDeep, "stack depth does not match"); < < if( subrdata->retCount == 2 ) { < WorkmapHead *original = outpro->getWorkmap(); < < assert( outcoming->flags == original->flags ); < assert( outcoming->depth == original->depth ); < < //merge local and stack variables < assert(sizeof(WorkmapElement) <= sizeof(StackmapElement)); //reverse the loop below if assert is broken < for( unsigned i = m_max_locals + workmap->depth; i >= 0; i-- ) { < WorkmapElement *from = &workmap->elements[i]; < WorkmapElement orig = original->elements[i]; < < StackmapElement *to = &outcoming->elements[i]; < //clear StackmapElement < to->init(); < < if( (tcr=new_scalar_constraint(from, to)) != VER_OK ) { < return tcr; < } < if( from->isVariable() == orig.isVariable() && < (from->isVariable() ? from->getVariable() == orig.getVariable() : from->getConst() == orig.getConst()) && < (tcr=new_scalar_constraint(&orig, to)) != VER_OK ) < { < return tcr; < } < } < //workmap converted to stackmap < outpro->clearInstrFlag(outpro->FF_ISWORKMAP); < } else { < assert(subrdata->retCount > 2); < //merge local and stack variables < for( unsigned i = 0; i < m_max_locals + workmap->depth; i++ ) { < WorkmapElement *from = &workmap->elements[i]; < StackmapElement *to = &outcoming->elements[i]; < < if( (tcr=new_scalar_constraint(from, to)) != VER_OK ) { < return tcr; < } < } < } < return VER_OK; --- > return error(VER_ErrorStackDeep, "Multiple returns to single jsr"); 2369,2373c2326 < SubroutineData *subrdata = outpro->getSubrData(m_max_locals + m_max_stack); < < if( subrdata->retCount > 1 ) { // there we track number of ret from the subroutine < StackmapHead* outcoming = outpro->getStackmap(); < workmap->depth = outcoming->depth; --- > SubroutineData *subrdata = outpro->getSubrData(m_stack_start + m_max_stack); 2375,2385c2328,2329 < unsigned i; < for( i = 0; i < m_max_locals; i++ ) { < if( outcoming->elements[i].isJsrModified() ) { < workmap->elements[i] = _WorkmapElement(outcoming->elements + i); < } < } < for( ; i < m_max_locals + workmap->depth; i++ ) { < workmap->elements[i] = _WorkmapElement(outcoming->elements + i); < } < < } else if( subrdata->retCount == 1 ) { --- > if( subrdata->retCount ) { > assert( subrdata->retCount == 1 ); 2390c2334 < for( i = 0; i < m_max_locals; i++ ) { --- > for( i = 0; i < m_stack_start; i++ ) { 2395c2339 < for( ; i < m_max_locals + workmap->depth; i++ ) { --- > for( ; i < m_stack_start + workmap->depth; i++ ) { 2406,2412d2349 < if( handler->flags ) { < //been there < if( handler->flags != workmap->flags ) return error(VER_ErrorDataFlow, "initialized states differ"); < } else { < handler->flags = workmap->flags; < } < 2414c2351 < for( unsigned i = 0; i < m_max_locals; i++ ) { --- > for( unsigned i = 0; i < m_stack_start; i++ ) { 2537c2474 < workmap = newWorkmap(m_max_locals + m_max_stack)->getWorkmap(); --- > workmap = newWorkmap(m_stack_start + m_max_stack)->getWorkmap(); 2541d2477 < workmap->flags = KNOW_STACK_DEPTH; 2544,2545c2480 < workmap->flags |= THIS_UNINIT; < if( !strcmp(method_get_name(m_method), "") && class_get_super_class(k_class) ) { --- > if( m_is_constructor ) { 2547a2483,2486 > > //another constructor has to be called > workmap->elements[m_max_locals] = _WorkmapElement(SM_THISUNINIT); > changed_locals[ m_max_locals ] = 1; diff verifier/Ver.cpp patched/verifier/Ver.cpp 126,127d125 < delete cl_data->pool; < delete cl_data->hash; 128a127,128 > delete cl_data->hash; > delete cl_data->pool; diff verifier/context.h patched/verifier/context.h 48c48,50 < {} --- > { > k_major = class_get_version( _klass ); > } 55c57 < char *error_message; --- > const char *error_message; 61a64,66 > //major version of current class > unsigned short k_major; > 73a79,84 > //is the current method construcor (and current class in not a j.l.Object)? > bool m_is_constructor; > > //m_max_locals or m_max_locals+1 if it's a constructor > unsigned m_stack_start; > 103c114,119 < FastStack stack; --- > MarkableStack stack; > > FastStack dead_code_stack; > bool dead_code_parsing; > > static const short MARK_SUBROUTINE_DONE = -1; 108,112d123 < //these two will serve as constants. these marks will be stored among valid addresses, so for each method < //we will find invalid numbers that are not the valid addresses and define these "constants" so that they < //are not the valid addresses < Address MARK_RESUME_JSR; < Address MARK_SUBROUTINE_DONE; 141d151 < assert(0); 142a153 > //assert(0); 156a168,172 > m_is_constructor = !strcmp(method_get_name(m_method), "") > && class_get_super_class(k_class); > > m_stack_start = m_max_locals + (m_is_constructor ? 1 : 0); > 161a178 > dead_code_stack.init(); 163c180 < changed_locals = (byte*)mem.malloc((m_max_locals & ~3) + 4); --- > changed_locals = (byte*)mem.malloc((m_stack_start & ~3) + 4); 173c190 < tc_memcpy(workmap, head->getWorkmap(), sizeof(WorkmapHead) + sizeof(WorkmapElement) * (m_max_locals + head->workmap.depth)); --- > tc_memcpy(workmap, head->getWorkmap(), sizeof(WorkmapHead) + sizeof(WorkmapElement) * (m_stack_start + head->workmap.depth)); 177d193 < workmap->flags = stackmap->flags; 180c196 < for( unsigned i = 0; i < m_max_locals + stackmap->depth; i++) { --- > for( unsigned i = 0; i < m_stack_start + stackmap->depth; i++) { 190c206 < int sz = m_max_locals + workmap->depth; --- > int sz = m_stack_start + workmap->depth; 215,216c231,232 < int sz = sizeof(PropsHead) + sizeof(StackmapElement) * (m_max_stack + m_max_locals) + //stackmap < ((sizeof(SubroutineData)+ m_max_locals) & (~3)) + 4; // fixed data and changed locals vector --- > int sz = sizeof(PropsHead) + sizeof(StackmapElement) * (m_max_stack + m_stack_start) + //stackmap > ((sizeof(SubroutineData)+ m_stack_start) & (~3)) + 4; // fixed data and changed locals vector 241,245d256 < //this function marks all JSRs that they can be resumed < Verifier_Result SubroutineDone(Address start); < < //Second pass: When all exit points for the subroutine invoked by this JSR instruction are passed < //we can resume dataflow from this point where we met JSR 247c258 < Verifier_Result ResumeJsr(Address jsr); --- > Verifier_Result SubroutineDone(Address start); 295c306 < pro = newStackmap(m_max_locals + depth); --- > pro = newStackmap(m_stack_start + depth); 296a308 > pro->getStackmap()->depth = depth; 308c320 < Verifier_Result tcr = add_incoming_value(type, &map->elements[m_max_locals]); --- > Verifier_Result tcr = add_incoming_value(type, &map->elements[m_stack_start]); 320c332 < return workmap->elements[ (--workmap->depth) + m_max_locals ]; --- > return workmap->elements[ (--workmap->depth) + m_stack_start ]; 326c338 < return workmap->elements[ workmap->depth + m_max_locals - depth - 1]; --- > return workmap->elements[ workmap->depth + m_stack_start - depth - 1]; 332c344 < workmap->elements[ (workmap->depth++) + m_max_locals ] = el; --- > workmap->elements[ (workmap->depth++) + m_stack_start ] = el; 338c350 < workmap->elements[ workmap->depth + m_max_locals ] = _WorkmapElement(value); --- > workmap->elements[ workmap->depth + m_stack_start ] = _WorkmapElement(value); 380c392 < locals_changed = true;; --- > locals_changed = true; 382d393 < //don't need to set "jsr modified" flag for constants 383a395,398 > > //don't need to set "jsr modified" flag for constants > //because they are already odd > assert(workmap->elements[idx].isJsrModified()); 497c512 < stack.push(target); --- > stack.xPush(target); 503c518 < stack.push(target); --- > stack.xPush(target); 514c529 < static __int16 read_int16(byte* ptr) { --- > static int16 read_int16(byte* ptr) { 519c534 < static __int32 read_int32(byte* ptr) { --- > static int32 read_int32(byte* ptr) { diff verifier/instr_props.h patched/verifier/instr_props.h 107c107 < int mask = 2 << ((instr % 4) * 2); --- > int shift = ((instr % 4) * 2); 109c109,110 < if( packed_flags[idx] & mask ) return 0; --- > int mask01 = 1 << shift; > int mask10 = 2 << shift; 111c112,116 < packed_flags[idx] |= mask; --- > //is an instruction > if( packed_flags[idx] & mask01 ) return 0; > > //mark as a middle > packed_flags[idx] |= mask10; diff verifier/stackmap.h patched/verifier/stackmap.h 28a29,34 > #ifdef WIN32 > #define intptr int64 > #else > #define intptr long > #endif > 52c58 < operator ==(_SmConstant other) { --- > int operator ==(_SmConstant other) { 56c62 < operator ==(unsigned other) { --- > int operator ==(unsigned other) { 60c66 < operator !=(_SmConstant other) { --- > int operator !=(_SmConstant other) { 64c70 < operator !=(unsigned other) { --- > int operator !=(unsigned other) { 179,184d184 < //list of *some* the JSR instructions calling a given subroutine < struct SubrCaller { < Address caller; //JSR address < SubrCaller *next; //next < }; < 190c190 < SubrCaller *callers; //wait-list of JSR instructions calling this subroutine --- > Address caller; //first JSR instruction that called this subroutine 193,201d192 < < //add one more JSR instruction to the wait list < void toWaitList(Memory *mem, Address jsr) { < SubrCaller* newcaller = (SubrCaller*)mem->malloc(sizeof(SubrCaller)); < newcaller->caller = jsr; < newcaller->next = callers; < < callers = newcaller; < } 296c287 < return (IncomingType*)( (int)incoming & ~3 ); --- > return (IncomingType*)( (intptr)incoming & ~3 ); 329,330c320,321 < int mask = (int)incoming & 3; < incoming = (IncomingType *) ((int)incoming & ~3); --- > intptr mask = (intptr)incoming & 3; > incoming = (IncomingType *) ((intptr)incoming & ~3); 338c329 < incoming = (IncomingType *) ((int)incoming | mask); --- > incoming = (IncomingType *) ((intptr)incoming | mask); 379c370 < return (int)incoming & 1; --- > return (int)(intptr)incoming & 1; 385c376 < incoming = (IncomingType *) ((int)incoming | 1); --- > incoming = (IncomingType *) ((intptr)incoming | 1); 391c382 < incoming = (IncomingType *) ((int)incoming & ~1); --- > incoming = (IncomingType *) ((intptr)incoming & ~1); 408c399 < return !((int)var_ptr & 1); --- > return !((intptr)var_ptr & 1); 418c409 < return (StackmapElement *) ((int)var_ptr & ~3); --- > return (StackmapElement *) ((intptr)var_ptr & ~3); 433c424 < return (int)var_ptr & 3; --- > return (int)(intptr)var_ptr & 3; 439c430 < var_ptr = (StackmapElement*)((int)var_ptr | 2); --- > var_ptr = (StackmapElement*)((intptr)var_ptr | 2); 467d457 < unsigned short flags; 474d463 < unsigned short flags; 545,549d533 < < const unsigned short KNOW_STACK_DEPTH = 1; < const unsigned short THIS_INIT = 2; < const unsigned short THIS_UNINIT = 4; < diff verifier/tpool.cpp patched/verifier/tpool.cpp 133c133 < if( from == SM_NULL || to == sm_get_const_object() ) return true; --- > if( from == SM_NULL ) return true; 279c279 < if( cp_idx >= k_cp_length ) return SM_BOGUS; --- > if( cp_idx >= k_cp_length || !cp_idx ) return SM_BOGUS; 292c292,293 < return sm_get_const_class(); --- > //check if it's a 1.5 class (major version is 49) > return context->k_major < 49 ? SM_BOGUS : sm_get_const_class(); 301c302 < if( cp_idx >= k_cp_length ) return SM_BOGUS; --- > if( cp_idx >= k_cp_length || !cp_idx ) return SM_BOGUS; 317c318 < return cp_idx < k_cp_length && class_get_cp_tag( k_class, cp_idx ) == _CONSTANT_Class; --- > return cp_idx && cp_idx < k_cp_length && class_get_cp_tag( k_class, cp_idx ) == _CONSTANT_Class; 321c322 < int vf_TypePool::cpool_get_class(unsigned short cp_idx, SmConstant *ref) { --- > int vf_TypePool::cpool_get_class(unsigned short cp_idx, SmConstant *ref, int expected_dim) { 328a330,341 > //validate dimensions > int ptr = 0; > while (name[ptr] == '[' ) { > ptr++; > } > //'name' already contains final '[', so max dimension of class 'name' is 255 > if( ptr < expected_dim || ptr > 255 ) return false; > > //array is not allowed here > if( ptr && expected_dim == -1 ) return false; > > 332c345 < if( ref ) *ref = get_ref_type(name, strlen(name)); --- > if( ref ) *ref = get_ref_type(name, (int)strlen(name)); 345c358,370 < size_t len = strlen(name); --- > int len = (int)strlen(name); > > > //validate dimensions > int ptr = 0; > while (name[ptr] == '[' ) { > ptr++; > } > > //'name' does not contain final '[', so max dimension of class 'name' is 254 > if( ptr > 254 ) return false; > > 367c392 < if( cp_idx >= k_cp_length || class_get_cp_tag( k_class, cp_idx ) != _CONSTANT_Fieldref ) { --- > if( !cp_idx || cp_idx >= k_cp_length || class_get_cp_tag( k_class, cp_idx ) != _CONSTANT_Fieldref ) { 375c400 < if( name_and_type_idx >= k_cp_length || class_get_cp_tag( k_class, name_and_type_idx ) != _CONSTANT_NameAndType ) return false; --- > if( !name_and_type_idx || name_and_type_idx >= k_cp_length || class_get_cp_tag( k_class, name_and_type_idx ) != _CONSTANT_NameAndType ) return false; 379c404 < //if( name_idx >= k_cp_length || class_get_cp_tag( k_class, name_idx ) != _CONSTANT_Utf8 ) return false; --- > //if( !name_idx || name_idx >= k_cp_length || class_get_cp_tag( k_class, name_idx ) != _CONSTANT_Utf8 ) return false; 383c408 < if( type_idx >= k_cp_length || class_get_cp_tag( k_class, type_idx ) != _CONSTANT_Utf8 ) return false; --- > if( !type_idx || type_idx >= k_cp_length || class_get_cp_tag( k_class, type_idx ) != _CONSTANT_Utf8 ) return false; 397c422 < if( cp_idx >= k_cp_length || class_get_cp_tag( k_class, cp_idx ) != expected_tag ) { --- > if( !cp_idx || cp_idx >= k_cp_length || class_get_cp_tag( k_class, cp_idx ) != expected_tag ) { 410c435 < if( name_and_type_idx >= k_cp_length || class_get_cp_tag( k_class, name_and_type_idx ) != _CONSTANT_NameAndType ) return false; --- > if( !name_and_type_idx || name_and_type_idx >= k_cp_length || class_get_cp_tag( k_class, name_and_type_idx ) != _CONSTANT_NameAndType ) return false; 414c439 < if( *name_idx >= k_cp_length || class_get_cp_tag( k_class, *name_idx ) != _CONSTANT_Utf8 ) return false; --- > if( !(*name_idx) || *name_idx >= k_cp_length || class_get_cp_tag( k_class, *name_idx ) != _CONSTANT_Utf8 ) return false; 418c443 < if( type_idx >= k_cp_length || class_get_cp_tag( k_class, type_idx ) != _CONSTANT_Utf8 ) return false; --- > if( !type_idx || type_idx >= k_cp_length || class_get_cp_tag( k_class, type_idx ) != _CONSTANT_Utf8 ) return false; diff verifier/tpool.h patched/verifier/tpool.h 61c61 < #define CLASS_NOT_LOADED ((class_handler)0xFFFFFFFF) --- > #define CLASS_NOT_LOADED ((class_handler)-1) 81c81,82 < int cpool_get_class(unsigned short cp_idx, SmConstant *ref); --- > int cpool_get_class(unsigned short cp_idx, SmConstant *ref, int expected_dim = 0); > 98c99 < return get_type(type_name, strlen(type_name) ); --- > return get_type(type_name, (int)strlen(type_name) ); 122c123 < (*cache) = get_ref_type(type_name, strlen(type_name)); --- > (*cache) = get_ref_type(type_name, (int)strlen(type_name)); 131c132 < return get_ref_type(_super, strlen(_super) ); --- > return get_ref_type(_super, (int)strlen(_super) ); diff verifier/ver_utils.h patched/verifier/ver_utils.h 146a147,180 > class MarkableStack : public FastStack { > // contains the following entries: > // no mask means zero mark > > // is pushed as {address} > // <0, 0> is pushed as {0, 0} > // is pushed as {address, mark, 0} > > public: > void xPop(Address *addr, short *mark) { > *addr = pop(); > *mark = (*addr) ? 0 : pop(); > > if( *mark ) { > *addr = pop(); > } > } > > void xPush(Address value) { > if( value ) { > push(value); > } else { > push(0); > push(0); > } > } > > void xPush(Address addr, short m) { > push(addr); > push(m); > push(0); > } > }; > 264c298 < int length = strlen(key); --- > int length = (int)strlen(key); 325c359 < return NewHashEntry(key, strlen(key)); --- > return NewHashEntry(key, (int)strlen(key)); 350c384 < if( *((__int32*) (key+idx) ) != *((__int32*) (h_key+idx) ) ) return false; --- > if( *((int32*) (key+idx) ) != *((int32*) (h_key+idx) ) ) return false; 371c405 < result += *((__int32*) (key+idx) ); --- > result += *((int32*) (key+idx) );