/src/main/java/jbse/algo/meta/Algo_SUN_REFLECTION_GETCALLERCLASS.java

https://github.com/pietrobraione/jbse · Java · 78 lines · 64 code · 11 blank · 3 comment · 6 complexity · fc31376e2c3f8b35418b019d56363044 MD5 · raw file

  1. package jbse.algo.meta;
  2. import static jbse.algo.UtilControlFlow.exitFromAlgorithm;
  3. import static jbse.algo.UtilControlFlow.throwNew;
  4. import static jbse.bc.Signatures.JAVA_METHOD_INVOKE;
  5. import static jbse.bc.Signatures.OUT_OF_MEMORY_ERROR;
  6. import java.util.List;
  7. import java.util.ListIterator;
  8. import java.util.function.Supplier;
  9. import jbse.algo.Algo_INVOKEMETA_Nonbranching;
  10. import jbse.algo.InterruptException;
  11. import jbse.algo.StrategyUpdate;
  12. import jbse.algo.exc.CannotInvokeMethodInCurrentContext;
  13. import jbse.bc.ClassFile;
  14. import jbse.common.exc.ClasspathException;
  15. import jbse.common.exc.InvalidInputException;
  16. import jbse.mem.Frame;
  17. import jbse.mem.State;
  18. import jbse.mem.exc.HeapMemoryExhaustedException;
  19. import jbse.tree.DecisionAlternative_NONE;
  20. import jbse.val.Reference;
  21. public final class Algo_SUN_REFLECTION_GETCALLERCLASS extends Algo_INVOKEMETA_Nonbranching {
  22. private Reference classRef; //set by cookMore
  23. @Override
  24. protected Supplier<Integer> numOperands() {
  25. return () -> 0;
  26. }
  27. @Override
  28. protected void cookMore(State state)
  29. throws ClasspathException, CannotInvokeMethodInCurrentContext,
  30. InterruptException, InvalidInputException {
  31. final List<Frame> stack = state.getStack();
  32. final ListIterator<Frame> it = stack.listIterator(stack.size());
  33. boolean firstSkipped = false;
  34. ClassFile classFile = null;
  35. while (it.hasPrevious()) {
  36. final Frame f = it.previous();
  37. if (firstSkipped) {
  38. //skip frames associated with java.lang.reflect.Method.invoke() and its implementation
  39. //(seemingly just java.lang.reflect.Method.invoke())
  40. if (f.getMethodSignature().equals(JAVA_METHOD_INVOKE)) {
  41. continue;
  42. }
  43. classFile = f.getMethodClass();
  44. break;
  45. } else {
  46. firstSkipped = true;
  47. }
  48. }
  49. if (classFile == null) {
  50. //this should happen only if this method is invoked by the root frame
  51. throw new CannotInvokeMethodInCurrentContext("The sun.reflect.Reflection.getCallerClass was invoked in a context where there is no caller (arguably the root frame).");
  52. }
  53. try {
  54. state.ensureInstance_JAVA_CLASS(this.ctx.getCalculator(), classFile);
  55. } catch (HeapMemoryExhaustedException e) {
  56. throwNew(state, this.ctx.getCalculator(), OUT_OF_MEMORY_ERROR);
  57. exitFromAlgorithm();
  58. }
  59. this.classRef = state.referenceToInstance_JAVA_CLASS(classFile);
  60. }
  61. @Override
  62. protected StrategyUpdate<DecisionAlternative_NONE> updater() {
  63. return (state, alt) -> {
  64. state.pushOperand(this.classRef);
  65. };
  66. }
  67. }