On 08/12/2013 02:11 PM, Brendan Eich wrote:

Can it be done other than in SpiderMonkey?
That's a great question.

What this implementation adds to SpiderMonkey is some random metadata attached to specific string instances, using a finer-grained concept of identity than JavaScript itself has --- JavaScript may consider two strings to be === that the taint distinguishes --- and code to propagate that metadata through string operations.

We could almost do this without modifying SpiderMonkey, by replacing all the primitives that propagate taint: String.prototype.*, Regex.prototype.*, and so on. However, we can't replace the '+' operator, which is critical; and we can't make that fine-grained distinction between one string and the other.

We might be able to do it with a Debugger source-rewriting hook, like the one Marc Feeley implemented. (That's all but ready to land; I need to take care of that before it bit-rots.)

What if JSAPI let the embedding provide, say, a StringLabeller instance, like the below? This doesn't really count as "removing it from SpiderMonkey", but it does make SpiderMonkey's responsibilities clearer, and leaves the details of what's collected to the embedding (I'd personally want to have the scripted caller location, for example).

class StringLabeller {

  class Label {
    virtual ~Label() = 0;
    void trace(JSTracer *trc) = 0;
  };

  enum Detail {
    REGEXP_MATCH,
    CHARAT,
    PLUS_OPERATOR,
    ...
  };

// Return the label to attach to the concatenation of |left| and |right|, which
  // we wanted while performing the operation given by |detail|.
virtual Label *concatenate(JSContext *cx, JSString *left, JSString *right,
                             Detail detail) = 0;

  // Return the label to attach to the substring of |original| starting at
  // |start| and extending for |length| characters, which we wanted while
  // performing the operation given by |detail|.
  virtual Label *substring(JSContext *cx, JSString *original,
                           size_t start, size_t length, Detail detail) = 0;

  virtual ~StringLabeller() = 0;
};

// Whenever operating on labelled strings in |rt|, use |labeller| to
// propagate the labels. This is a best-effort interface: SM may drop
// labels if it's too hard to propagate them.
void JS_SetStringLabeller(JSRuntime *rt, StringLabeller *labeller);

// Return a new string equal to |original| that has |label| attached.
JSString *JS_AttachStringLabel(JSString *original, StringLabeller::Label *label);

// Return the label attached to |string|, or NULL if there is none.
JSString *JS_GetStringLabel(JSString *string);


_______________________________________________
dev-tech-js-engine-internals mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-js-engine-internals

Reply via email to