public LHS toLHS(CallStack callstack, Interpreter interpreter) throws EvalError { try { return getName(callstack.top()).toLHS(callstack, interpreter); } catch (UtilEvalError e) { throw e.toEvalError(this, callstack); } }
// Throws a program exception with the given message. private void error(String message) throws ProgramException { throw new ProgramException( message + " in " + callStack.getTopFunction() + "." + currentInstruction.getIndexInFunction()); }
Object toObject(CallStack callstack, Interpreter interpreter, boolean forceClass) throws EvalError { try { return getName(callstack.top()).toObject(callstack, interpreter, forceClass); } catch (UtilEvalError e) { throw e.toEvalError(this, callstack); } }
public Class toClass(CallStack callstack, Interpreter interpreter) throws EvalError { try { return getName(callstack.top()).toClass(); } catch (ClassNotFoundException e) { throw new EvalError(e.getMessage(), this, callstack); } catch (UtilEvalError e2) { // ClassPathException is a type of UtilEvalError throw e2.toEvalError(this, callstack); } }
private void afterExecutionImpl(final String sqlString) { if (JiraSystemProperties.getInstance().isXsrfDiagnostics()) { final String requestURL = MDC.get("jira.request.url"); if (isMutatingSQL(sqlString)) { HttpServletRequest request = ActionContext.getRequest(); if (request != null && request.getAttribute(XSRF_VULNERABILITY_DETECTION_SQLINTERCEPTOR_DONE) == null) { // setting this into the request will make things a lot faster request.setAttribute(XSRF_VULNERABILITY_DETECTION_SQLINTERCEPTOR_DONE, "true"); CallStack callStack = new CallStack(); if (callStack.hasMethodsWeAreInterestedIn() && !callStack.isProtectedAction()) { log.error("XSRF VULNERABILITY DETECTED"); log.error("requestURL: " + requestURL); log.error("sql: " + sqlString); log.error("CallStack:", callStack); } } } } }
/** * Calls a function according to the given function number stating that the given number of * arguments have been pushed onto the stack * * <p>If callerIsBuiltIn then the caller is a builtIn function that called this function through * callFunctionFromBuiltIn. If address is -1 then a native function should be looked up and * called. */ public void callFunction( short address, short numberOfArguments, String functionName, boolean callerIsBuiltIn) throws ProgramException { stackFrames.addElement(new Integer(workingStackSegment.getStartAddress())); workingStackSegment.setStartAddress(getSP() + 5); if (callerIsBuiltIn) { pushValue(MAIN_STACK, VMProgram.BUILTIN_FUNCTION_ADDRESS); } else { pushValue(MAIN_STACK, program.getPC()); } pushFromRAM(MAIN_STACK, Definitions.LOCAL_POINTER_ADDRESS); pushFromRAM(MAIN_STACK, Definitions.ARG_POINTER_ADDRESS); pushFromRAM(MAIN_STACK, Definitions.THIS_POINTER_ADDRESS); pushFromRAM(MAIN_STACK, Definitions.THAT_POINTER_ADDRESS); ram.setValueAt( Definitions.ARG_POINTER_ADDRESS, (short) (getSP() - numberOfArguments - 5), false); ram.setValueAt(Definitions.LOCAL_POINTER_ADDRESS, getSP(), false); // enable in the arg segment only the number of args that were sent to the called function. argSegment.setEnabledRange( argSegment.getStartAddress(), argSegment.getStartAddress() + numberOfArguments - 1, true); if (address == VMProgram.BUILTIN_FUNCTION_ADDRESS) { // Perform some actions normally done in the function() method localSegment.setEnabledRange( localSegment.getStartAddress(), localSegment.getStartAddress() - 1, true); // no local variables callStack.pushFunction(functionName + " (built-in)"); staticSegment.setEnabledRange(0, -1, true); // empty static segment // Read parameters from the stack short[] params = new short[numberOfArguments]; for (int i = 0; i < numberOfArguments; ++i) { params[i] = argSegment.getValueAt(i); } // Call the built-in implementation builtInFunctionsRunner.callBuiltInFunction(functionName, params); } else if (address >= 0 || address < program.getSize()) { program.setPC(address); program.setPC(address); // make sure previouspc isn't pc-1 // which might happen if the calling // function called this function in the // last line before the "return" and // was declared just before this function. // In this case encountering the "function" // command will issue an error about // "missing return"... } else { error("Illegal call address"); } }
public String getScriptStackTrace() { if (callstack == null) return "<Unknown>"; String trace = ""; CallStack stack = callstack.copy(); while (stack.depth() > 0) { NameSpace ns = stack.pop(); SimpleNode node = ns.getNode(); if (ns.isMethod) { trace = trace + "\nCalled from method: " + ns.getName(); if (node != null) trace += " : at Line: " + node.getLineNumber() + " : in file: " + node.getSourceFile() + " : " + node.getText(); } } return trace; }
/** * Here Starts the code of a function according to the given function name that has the given * number of local variables. * * @param numberOfLocals The number of local variables */ public void function(short numberOfLocals) throws ProgramException { short newSP = (short) (getSP() + numberOfLocals); checkSP(newSP); workingStackSegment.setStartAddress(newSP); // disable non relevant range of the local segment - enable only the number // of locals of this function. localSegment.setEnabledRange(getSP(), newSP - 1, true); for (int i = 0; i < numberOfLocals; i++) { pushValue(MAIN_STACK, (short) 0); } String functionName = currentInstruction.getStringArg(); // adds the new function to the top of the call stack. callStack.pushFunction(functionName); // sets the static segment range setStaticRange(functionName); }
/** * Parse the BSHBlock for for the class definition and generate the class using ClassGenerator. */ public static Class generateClassImpl( String name, Modifiers modifiers, Class[] interfaces, Class superClass, BSHBlock block, boolean isInterface, CallStack callstack, Interpreter interpreter) throws EvalError { // Scripting classes currently requires accessibility // This can be eliminated with a bit more work. try { Capabilities.setAccessibility(true); } catch (Capabilities.Unavailable e) { throw new EvalError( "Defining classes currently requires reflective Accessibility.", block, callstack); } NameSpace enclosingNameSpace = callstack.top(); String packageName = enclosingNameSpace.getPackage(); String className = enclosingNameSpace.isClass ? (enclosingNameSpace.getName() + "$" + name) : name; String fqClassName = packageName == null ? className : packageName + "." + className; BshClassManager bcm = interpreter.getClassManager(); // Race condition here... bcm.definingClass(fqClassName); // Create the class static namespace NameSpace classStaticNameSpace = new NameSpace(enclosingNameSpace, className); classStaticNameSpace.isClass = true; callstack.push(classStaticNameSpace); // Evaluate any inner class class definitions in the block // effectively recursively call this method for contained classes first block.evalBlock(callstack, interpreter, true /*override*/, ClassNodeFilter.CLASSCLASSES); // Generate the type for our class Variable[] variables = getDeclaredVariables(block, callstack, interpreter, packageName); DelayedEvalBshMethod[] methods = getDeclaredMethods(block, callstack, interpreter, packageName); ClassGeneratorUtil classGenerator = new ClassGeneratorUtil( modifiers, className, packageName, superClass, interfaces, variables, methods, classStaticNameSpace, isInterface); byte[] code = classGenerator.generateClass(); // if debug, write out the class file to debugClasses directory if (DEBUG_DIR != null) try { FileOutputStream out = new FileOutputStream(DEBUG_DIR + '/' + className + ".class"); out.write(code); out.close(); } catch (IOException e) { throw new IllegalStateException( "cannot create file " + DEBUG_DIR + '/' + className + ".class", e); } // Define the new class in the classloader Class genClass = bcm.defineClass(fqClassName, code); // import the unq name into parent enclosingNameSpace.importClass(fqClassName.replace('$', '.')); try { classStaticNameSpace.setLocalVariable( ClassGeneratorUtil.BSHINIT, block, false /*strictJava*/); } catch (UtilEvalError e) { throw new InterpreterError("unable to init static: " + e); } // Give the static space its class static import // important to do this after all classes are defined classStaticNameSpace.setClassStatic(genClass); // evaluate the static portion of the block in the static space block.evalBlock(callstack, interpreter, true /*override*/, ClassNodeFilter.CLASSSTATIC); callstack.pop(); if (!genClass.isInterface()) { // Set the static bsh This callback String bshStaticFieldName = ClassGeneratorUtil.BSHSTATIC + className; try { LHS lhs = Reflect.getLHSStaticField(genClass, bshStaticFieldName); lhs.assign(classStaticNameSpace.getThis(interpreter), false /*strict*/); } catch (Exception e) { throw new InterpreterError("Error in class gen setup: " + e); } } bcm.doneDefiningClass(fqClassName); return genClass; }
public Object eval(CallStack callstack, Interpreter interpreter) throws EvalError { Class elementType = null; SimpleNode expression; SimpleNode statement = null; NameSpace enclosingNameSpace = callstack.top(); SimpleNode firstNode = ((SimpleNode) jjtGetChild(0)); int nodeCount = jjtGetNumChildren(); if (firstNode instanceof BSHType) { elementType = ((BSHType) firstNode).getType(callstack, interpreter); expression = ((SimpleNode) jjtGetChild(1)); if (nodeCount > 2) { statement = ((SimpleNode) jjtGetChild(2)); } } else { expression = firstNode; if (nodeCount > 1) { statement = ((SimpleNode) jjtGetChild(1)); } } BlockNameSpace eachNameSpace = new BlockNameSpace(enclosingNameSpace); callstack.swap(eachNameSpace); final Object iteratee = expression.eval(callstack, interpreter); if (iteratee == Primitive.NULL) { throw new EvalError( "The collection, array, map, iterator, or " + "enumeration portion of a for statement cannot be null.", this, callstack); } CollectionManager cm = CollectionManager.getCollectionManager(); if (!cm.isBshIterable(iteratee)) { throw new EvalError("Can't iterate over type: " + iteratee.getClass(), this, callstack); } BshIterator iterator = cm.getBshIterator(iteratee); Object returnControl = Primitive.VOID; while (iterator.hasNext()) { try { Object value = iterator.next(); if (value == null) { value = Primitive.NULL; } if (elementType != null) { eachNameSpace.setTypedVariable( varName /*name*/, elementType /*type*/, value /*value*/, new Modifiers() /*none*/); } else { eachNameSpace.setVariable(varName, value, false); } } catch (UtilEvalError e) { throw e.toEvalError("for loop iterator variable:" + varName, this, callstack); } boolean breakout = false; // switch eats a multi-level break here? if (statement != null) { // not empty statement Object ret = statement.eval(callstack, interpreter); if (ret instanceof ReturnControl) { switch (((ReturnControl) ret).kind) { case RETURN: returnControl = ret; breakout = true; break; case CONTINUE: break; case BREAK: breakout = true; break; } } } if (breakout) { break; } } callstack.swap(enclosingNameSpace); return returnControl; }
/** Returns the value of the function to the top of the stack. */ public void returnFromFunction() throws ProgramException { // make sure that there's somewhere to return to (old local <> 0) if (stackSegment.getValueAt(Definitions.LOCAL_POINTER_ADDRESS) == 0) throw new ProgramException( "Nowhere to return to in " + getCallStack().getTopFunction() + "." + getCurrentInstruction().getIndexInFunction()); // done in order to clear the method stack's contents workingStackSegment.setStartAddress(getSP()); bus.send(ram, Definitions.LOCAL_POINTER_ADDRESS, ram, Definitions.R13_ADDRESS); // R13 = lcl bus.send( stackSegment, stackSegment.getValueAt(Definitions.LOCAL_POINTER_ADDRESS) - 5, ram, Definitions.R14_ADDRESS); // R14 = return address bus.send( stackSegment, getSP() - 1, stackSegment, ram.getValueAt(Definitions.ARG_POINTER_ADDRESS)); // *arg = return value setSP((short) (ram.getValueAt(Definitions.ARG_POINTER_ADDRESS) + 1)); // SP = arg + 1 bus.send( stackSegment, ram.getValueAt(Definitions.R13_ADDRESS) - 1, ram, Definitions.THAT_POINTER_ADDRESS); // that = *(R13 - 1) bus.send( stackSegment, ram.getValueAt(Definitions.R13_ADDRESS) - 2, ram, Definitions.THIS_POINTER_ADDRESS); // this = *(R13 - 2) bus.send( stackSegment, ram.getValueAt(Definitions.R13_ADDRESS) - 3, ram, Definitions.ARG_POINTER_ADDRESS); // arg = *(R13 - 3) bus.send( stackSegment, ram.getValueAt(Definitions.R13_ADDRESS) - 4, ram, Definitions.LOCAL_POINTER_ADDRESS); // lcl = *(R13 - 4) // removes the top function from the call stack callStack.popFunction(); // check whether there is a "calling frame" if (stackFrames.size() > 0) { // retrieve stack frame address of old function int frameAddress = ((Integer) stackFrames.lastElement()).intValue(); stackFrames.removeElementAt(stackFrames.size() - 1); workingStackSegment.setStartAddress(frameAddress); // disable non relevant range of the local segment - enable only the locals // of the function that we returned to. localSegment.setEnabledRange( Math.max(localSegment.getStartAddress(), Definitions.STACK_START_ADDRESS), frameAddress - 1, true); // enable in the arg segment only the number of args that were sent to the function // that we returned to. argSegment.setEnabledRange( argSegment.getStartAddress(), localSegment.getStartAddress() - 6, true); // enable this, that according to their retrieved pointers thisSegment.setEnabledRange( Math.max(thisSegment.getStartAddress(), Definitions.HEAP_START_ADDRESS), Definitions.HEAP_END_ADDRESS, true); thatSegment.setEnabledRange( Math.max(thatSegment.getStartAddress(), Definitions.HEAP_START_ADDRESS), Definitions.SCREEN_END_ADDRESS, true); } /* else { error("Nowhere to return to"); } */ // Allow return if we previously had "function" even with no call - // For the SimpleFunction test short returnAddress = ram.getValueAt(Definitions.R14_ADDRESS); if (returnAddress == VMProgram.BUILTIN_FUNCTION_ADDRESS) { staticSegment.setEnabledRange(0, -1, true); // empty static segment builtInFunctionsRunner.returnToBuiltInFunction(popValue(METHOD_STACK)); } else if (returnAddress >= 0 && returnAddress < program.getSize()) { // sets the static segment range if (stackFrames.size() > 0) { setStaticRange(callStack.getTopFunction()); } else { staticSegment.setStartAddress(Definitions.VAR_START_ADDRESS); staticSegment.setEnabledRange( Definitions.VAR_START_ADDRESS, Definitions.VAR_END_ADDRESS - 1, true); } program.setPC((short) (returnAddress - 1)); // set previousPC correctly program.setPC(returnAddress); // pc = *sp } else { error("Illegal return address"); } }
/** * Executes the current instruction (Program at pc). Returns false if END command, true otherwise. */ public void executeInstruction() throws ProgramException { currentInstruction = program.getNextInstruction(); if (currentInstruction == null) throw new ProgramException("No more instructions to execute"); switch (currentInstruction.getOpCode()) { case HVMInstructionSet.ADD_CODE: add(); break; case HVMInstructionSet.SUBSTRACT_CODE: substract(); break; case HVMInstructionSet.NEGATE_CODE: negate(); break; case HVMInstructionSet.EQUAL_CODE: equal(); break; case HVMInstructionSet.GREATER_THAN_CODE: greaterThan(); break; case HVMInstructionSet.LESS_THAN_CODE: lessThan(); break; case HVMInstructionSet.AND_CODE: and(); break; case HVMInstructionSet.OR_CODE: or(); break; case HVMInstructionSet.NOT_CODE: not(); break; case HVMInstructionSet.PUSH_CODE: push(currentInstruction.getArg0(), currentInstruction.getArg1()); break; case HVMInstructionSet.POP_CODE: pop(currentInstruction.getArg0(), currentInstruction.getArg1()); break; case HVMInstructionSet.GOTO_CODE: goTo(currentInstruction.getArg0()); break; case HVMInstructionSet.IF_GOTO_CODE: ifGoTo(currentInstruction.getArg0()); break; case HVMInstructionSet.FUNCTION_CODE: if (program.getCurrentPC() == program.getPreviousPC() + 1) throw new ProgramException("Missing return in " + callStack.getTopFunction()); function(currentInstruction.getArg0()); break; case HVMInstructionSet.RETURN_CODE: returnFromFunction(); break; case HVMInstructionSet.CALL_CODE: callFunction( currentInstruction.getArg0(), currentInstruction.getArg1(), currentInstruction.getStringArg(), false); break; } }
public EvalError(String s, SimpleNode node, CallStack callstack) { setMessage(s); this.node = node; // freeze the callstack for the stack trace. if (callstack != null) this.callstack = callstack.copy(); }