예제 #1
0
 /** 11.2.1 assignment with left-hand-side property accessor. */
 @Override
 public void visit(WritePropertyNode n, State state) {
   // get the base value, coerce with ToObject
   Value baseval = state.readRegister(n.getBaseRegister());
   baseval = UnknownValueResolver.getRealValue(baseval, state);
   m.visitPropertyAccess(n, baseval);
   Set<ObjectLabel> objlabels = Conversion.toObjectLabels(state, n, baseval, c);
   if (objlabels.isEmpty() && !Options.get().isPropagateDeadFlow()) {
     state.setToNone();
     return;
   }
   state.writeRegister(
       n.getBaseRegister(),
       Value.makeObject(objlabels)); // if null/undefined, an exception would have been thrown via
   // toObjectLabels
   // get the property name value, separate the undefined/null/NaN components, coerce with ToString
   Value propertyval;
   int propertyreg;
   if (n.isPropertyFixed()) {
     propertyreg = AbstractNode.NO_VALUE;
     propertyval = Value.makeStr(n.getPropertyString());
   } else {
     propertyreg = n.getPropertyRegister();
     propertyval = state.readRegister(propertyreg);
     propertyval = UnknownValueResolver.getRealValue(propertyval, state);
   }
   boolean maybe_undef = propertyval.isMaybeUndef();
   boolean maybe_null = propertyval.isMaybeNull();
   boolean maybe_nan = propertyval.isMaybeNaN();
   propertyval = propertyval.restrictToNotNullNotUndef().restrictToNotNaN();
   Str propertystr = Conversion.toString(propertyval, propertyreg, c);
   // get the value to be written
   Value v = state.readRegister(n.getValueRegister());
   NativeFunctions.updateArrayLength(n, state, objlabels, propertystr, v, n.getValueRegister(), c);
   // write the object property value, as fixed property name or unknown property name, and
   // separately for "undefined"/"null"/"NaN"
   state.writeProperty(objlabels, propertystr, v, true, maybe_undef || maybe_null || maybe_nan);
   if (maybe_undef && !propertystr.isMaybeStr("undefined"))
     state.writeProperty(
         objlabels, Value.makeTemporaryStr("undefined"), v, true, !propertystr.isNotStr());
   if (maybe_null && !propertystr.isMaybeStr("null"))
     state.writeProperty(
         objlabels, Value.makeTemporaryStr("null"), v, true, !propertystr.isNotStr());
   if (maybe_nan && !propertystr.isMaybeStr("NaN"))
     state.writeProperty(
         objlabels, Value.makeTemporaryStr("NaN"), v, true, !propertystr.isNotStr());
   m.visitPropertyWrite(n, objlabels, propertystr); // TODO: more monitoring around here?
   if (Options.get().isEvalStatistics()
       && propertystr.getStr() != null
       && propertystr.getStr().equals("innerHTML")) {
     m.visitInnerHTMLWrite(n, v);
   }
   m.visitVariableOrProperty(
       n.getPropertyString(), n.getSourceLocation(), v, state.getContext(), state);
 }
예제 #2
0
 /** 11.13 and 11.4.1 assignment with 'delete' operator. */
 @Override
 public void visit(DeletePropertyNode n, State state) {
   Value v;
   if (n.isVariable()) {
     v = state.deleteVariable(n.getVariableName());
     m.visitVariableOrProperty(
         n.getVariableName(), n.getSourceLocation(), v, state.getContext(), state);
   } else {
     Value baseval = state.readRegister(n.getBaseRegister());
     baseval = UnknownValueResolver.getRealValue(baseval, state);
     m.visitPropertyAccess(n, baseval);
     if (baseval.isMaybeNull() || baseval.isMaybeUndef()) {
       Exceptions.throwTypeError(state, c);
       if (baseval.isNullOrUndef() && !Options.get().isPropagateDeadFlow()) {
         state.setToNone();
         return;
       }
     }
     baseval = baseval.restrictToNotNullNotUndef();
     state.writeRegister(n.getBaseRegister(), baseval);
     Set<ObjectLabel> objlabels = Conversion.toObjectLabels(state, n, baseval, c);
     if (objlabels.isEmpty() && !Options.get().isPropagateDeadFlow()) {
       state.setToNone();
       return;
     }
     Str propertystr;
     if (n.isPropertyFixed()) {
       propertystr = Value.makeStr(n.getPropertyString());
     } else {
       Value propertyval = state.readRegister(n.getPropertyRegister());
       propertystr = Conversion.toString(propertyval, n.getPropertyRegister(), c);
     }
     v = state.deleteProperty(objlabels, propertystr, false);
   }
   if (v.isNotPresent() && !Options.get().isPropagateDeadFlow()) {
     state.setToNone();
     return;
   }
   if (n.getResultRegister() != AbstractNode.NO_VALUE)
     state.writeRegister(n.getResultRegister(), v);
 }
예제 #3
0
  /** 11.2.2, 11.2.3, 13.2.1, and 13.2.2 'new' / function call. */
  @Override
  public void visit(CallNode n, State state) {
    if (n.getFunctionRegister()
        != AbstractNode.NO_VALUE) // old style call (where the function is given as a variable read)
    FunctionCalls.callFunction(
          new OrdinaryCallInfo(n, state) {

            @Override
            public Value getFunctionValue() {
              Value functionValue = state.readRegister(n.getFunctionRegister());
              if (n.getLiteralConstructorKind() != null) {
                // these literal invocations can not be spurious in ES5
                switch (n.getLiteralConstructorKind()) {
                  case ARRAY:
                    functionValue =
                        Value.makeObject(new ObjectLabel(ECMAScriptObjects.ARRAY, Kind.FUNCTION));
                    break;
                  case REGEXP:
                    functionValue =
                        Value.makeObject(new ObjectLabel(ECMAScriptObjects.REGEXP, Kind.FUNCTION));
                    break;
                  default:
                    throw new AnalysisException(
                        "Unhandled literal constructor type: " + n.getLiteralConstructorKind());
                }
              }
              return functionValue;
            }

            @Override
            public Set<ObjectLabel> prepareThis(State caller_state, State callee_state) {
              return UserFunctionCalls.determineThis(
                  n, caller_state, callee_state, c, n.getBaseRegister());
            }
          },
          state,
          c);
    else { // getPropertyString / getPropertyRegister - like ReadPropertyNode
      Value baseval = state.readRegister(n.getBaseRegister());
      baseval = UnknownValueResolver.getRealValue(baseval, state);
      Set<ObjectLabel> objlabels =
          baseval.getObjectLabels(); // the ReadPropertyNode has updated baseval to account for
      // ToObject
      Value propertyval;
      int propertyreg;
      if (n.isPropertyFixed()) {
        propertyreg = AbstractNode.NO_VALUE;
        propertyval = Value.makeStr(n.getPropertyString());
      } else {
        propertyreg = n.getPropertyRegister();
        propertyval = state.readRegister(propertyreg);
        propertyval = UnknownValueResolver.getRealValue(propertyval, state);
      }
      boolean maybe_undef = propertyval.isMaybeUndef();
      boolean maybe_null = propertyval.isMaybeNull();
      boolean maybe_nan = propertyval.isMaybeNaN();
      propertyval = propertyval.restrictToNotNullNotUndef().restrictToNotNaN();
      Str propertystr = Conversion.toString(propertyval, propertyreg, c);
      // read the object property value, as fixed property name or unknown property name, and
      // separately for "undefined"/"null"/"NaN"
      Map<ObjectLabel, Set<ObjectLabel>> target2this = newMap();
      List<Value> nonfunctions = newList();
      for (ObjectLabel objlabel :
          objlabels) { // find possible targets for each possible base object
        Set<ObjectLabel> singleton = singleton(objlabel);
        Value v;
        boolean read_undefined = false;
        boolean read_null = false;
        boolean read_nan = false;
        if (propertystr.isMaybeSingleStr()) {
          String propertyname = propertystr.getStr();
          v = state.readPropertyValue(singleton, propertyname);
        } else if (!propertystr.isNotStr()) {
          v = state.readPropertyValue(singleton, propertystr);
          read_undefined = propertystr.isMaybeStr("undefined");
          read_null = propertystr.isMaybeStr("null");
          read_nan = propertystr.isMaybeStr("NaN");
        } else v = Value.makeNone();
        if (maybe_undef && !read_undefined) {
          v = UnknownValueResolver.join(v, state.readPropertyValue(singleton, "undefined"), state);
        }
        if (maybe_null && !read_null) {
          v = UnknownValueResolver.join(v, state.readPropertyValue(singleton, "null"), state);
        }
        if (maybe_nan && !read_nan) {
          v = UnknownValueResolver.join(v, state.readPropertyValue(singleton, "NaN"), state);
        }
        v = UnknownValueResolver.getRealValue(v, state);

        // finally, remove all the TAJS hooks, which are spurious if accessed through a dynamic
        // property
        if (!n.isPropertyFixed()) {
          v = JSGlobal.removeTAJSSpecificFunctions(v);
        }

        for (ObjectLabel target : v.getObjectLabels()) {
          if (target.getKind() == Kind.FUNCTION) {
            addToMapSet(target2this, target, objlabel);
          } else {
            nonfunctions.add(Value.makeObject(target));
          }
        }
        if (v.isMaybePrimitive()) {
          nonfunctions.add(v.restrictToNotObject());
        }
      }
      // do calls to each target with the corresponding values of this
      for (Entry<ObjectLabel, Set<ObjectLabel>> me : target2this.entrySet()) {
        ObjectLabel target = me.getKey();
        Set<ObjectLabel> this_objs = me.getValue();
        FunctionCalls.callFunction(
            new OrdinaryCallInfo(n, state) {

              @Override
              public Value getFunctionValue() {
                return Value.makeObject(target);
              }

              @Override
              public Set<ObjectLabel> prepareThis(State caller_state, State callee_state) {
                return this_objs;
              }
            },
            state,
            c);
      }
      // also model calls to non-function values
      FunctionCalls.callFunction(
          new OrdinaryCallInfo(n, state) {

            @Override
            public Value getFunctionValue() {
              return Value.join(nonfunctions);
            }

            @Override
            public Set<ObjectLabel> prepareThis(State caller_state, State callee_state) {
              return Collections.emptySet();
            }
          },
          state,
          c);
    }
  }
예제 #4
0
 /** 11.2.1 assignment with right-hand-side property accessor. */
 @Override
 public void visit(ReadPropertyNode n, State state) {
   // get the base value, coerce with ToObject
   Value baseval = state.readRegister(n.getBaseRegister());
   baseval = UnknownValueResolver.getRealValue(baseval, state);
   m.visitPropertyAccess(n, baseval);
   Set<ObjectLabel> objlabels = Conversion.toObjectLabels(state, n, baseval, c);
   if (objlabels.isEmpty() && !Options.get().isPropagateDeadFlow()) {
     state.setToNone();
     return;
   }
   state.writeRegister(
       n.getBaseRegister(),
       Value.makeObject(objlabels)); // if null/undefined, an exception would have been thrown via
   // toObjectLabels
   // get the property name value, separate the undefined/null/NaN components, coerce with ToString
   Value propertyval;
   int propertyreg;
   if (n.isPropertyFixed()) {
     propertyreg = AbstractNode.NO_VALUE;
     propertyval = Value.makeStr(n.getPropertyString());
   } else {
     propertyreg = n.getPropertyRegister();
     propertyval = state.readRegister(propertyreg);
     propertyval = UnknownValueResolver.getRealValue(propertyval, state);
   }
   boolean maybe_undef = propertyval.isMaybeUndef();
   boolean maybe_null = propertyval.isMaybeNull();
   boolean maybe_nan = propertyval.isMaybeNaN();
   propertyval = propertyval.restrictToNotNullNotUndef().restrictToNotNaN();
   Str propertystr = Conversion.toString(propertyval, propertyreg, c);
   // read the object property value, as fixed property name or unknown property name, and
   // separately for "undefined"/"null"/"NaN"
   Value v;
   boolean read_undefined = false;
   boolean read_null = false;
   boolean read_nan = false;
   if (propertystr.isMaybeSingleStr()) {
     String propertyname = propertystr.getStr();
     m.visitReadProperty(n, objlabels, propertystr, maybe_undef || maybe_null || maybe_nan, state);
     v = state.readPropertyValue(objlabels, propertyname);
     m.visitPropertyRead(n, objlabels, propertystr, state, true);
   } else if (!propertystr.isNotStr()) {
     m.visitReadProperty(n, objlabels, propertystr, true, state);
     m.visitPropertyRead(n, objlabels, propertystr, state, true);
     v = state.readPropertyValue(objlabels, propertystr);
     read_undefined = propertystr.isMaybeStr("undefined");
     read_null = propertystr.isMaybeStr("null");
     read_nan = propertystr.isMaybeStr("NaN");
   } else v = Value.makeNone();
   if (maybe_undef && !read_undefined) {
     m.visitReadProperty(n, objlabels, Value.makeTemporaryStr("undefined"), true, state);
     v = UnknownValueResolver.join(v, state.readPropertyValue(objlabels, "undefined"), state);
   }
   if (maybe_null && !read_null) {
     m.visitReadProperty(n, objlabels, Value.makeTemporaryStr("null"), true, state);
     v = UnknownValueResolver.join(v, state.readPropertyValue(objlabels, "null"), state);
   }
   if (maybe_nan && !read_nan) {
     m.visitReadProperty(n, objlabels, Value.makeTemporaryStr("NaN"), true, state);
     v = UnknownValueResolver.join(v, state.readPropertyValue(objlabels, "NaN"), state);
   }
   // remove all the TAJS hooks, which are spurious if accessed through a dynamic property
   if (!n.isPropertyFixed()) {
     v = JSGlobal.removeTAJSSpecificFunctions(v);
   }
   m.visitVariableOrProperty(
       n.getPropertyString(), n.getSourceLocation(), v, state.getContext(), state);
   m.visitRead(n, v, state);
   if (v.isNotPresent() && !Options.get().isPropagateDeadFlow()) {
     state.setToNone();
     return;
   }
   // store the resulting value
   if (n.getResultRegister() != AbstractNode.NO_VALUE)
     state.writeRegister(n.getResultRegister(), v);
 }