From 19ef468f2de00e656dd1b732ff48db808879aec2 Mon Sep 17 00:00:00 2001 From: Thomas Barber Date: Tue, 3 Dec 2024 13:20:06 +0000 Subject: [PATCH] Dump StringTaint to file via a Spewer --- js/moz.configure | 9 +++++++ js/src/jsapi.cpp | 2 ++ js/src/jstaint.cpp | 49 ++++++++++++++++++++++++++++++++++ js/src/jstaint.h | 3 +++ js/src/util/StructuredSpewer.h | 3 ++- js/src/vm/JSONPrinter.cpp | 11 ++++++++ js/src/vm/JSONPrinter.h | 3 +++ 7 files changed, 79 insertions(+), 1 deletion(-) diff --git a/js/moz.configure b/js/moz.configure index cbcaf38f01c9d..b52afe7c75230 100644 --- a/js/moz.configure +++ b/js/moz.configure @@ -494,6 +494,15 @@ set_config("JS_JITSPEW", depends_if("--enable-jitspew")(lambda _: True)) set_define("JS_STRUCTURED_SPEW", depends_if("--enable-jitspew")(lambda _: True)) set_config("JS_STRUCTURED_SPEW", depends_if("--enable-jitspew")(lambda _: True)) +option( + "--enable-taintspew", + default=False, + help="{Enable|Disable} the taint flow spew variable", +) + +# Also enable the structured spewer for tainting +set_define("JS_STRUCTURED_SPEW", depends_if("--enable-taintspew")(lambda _: True)) +set_config("JS_STRUCTURED_SPEW", depends_if("--enable-taintspew")(lambda _: True)) @depends("--enable-jit", "--enable-jitspew", simulator, target, moz_debug) def jit_disasm_arm(jit_enabled, spew, simulator, target, debug): diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index c4fa087b08251..8e02208c3ecf6 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -5072,6 +5072,8 @@ JS_ReportTaintSink(JSContext* cx, JS::HandleString str, const char* sink, JS::Ha RootedValue rval(cx); JS_CallFunction(cx, nullptr, report, arguments, &rval); MOZ_ASSERT(!cx->isExceptionPending()); + + MaybeSpewStringTaint(cx, str); } JS_PUBLIC_API bool JS::FinishIncrementalEncoding(JSContext* cx, diff --git a/js/src/jstaint.cpp b/js/src/jstaint.cpp index 22a4da241f96a..7a2897a9a4202 100644 --- a/js/src/jstaint.cpp +++ b/js/src/jstaint.cpp @@ -17,6 +17,7 @@ #include "js/ErrorReport.h" #include "js/UniquePtr.h" #include "vm/FrameIter.h" +#include "vm/JSAtomUtils.h" #include "vm/JSContext.h" #include "vm/JSFunction.h" #include "vm/StringType.h" @@ -371,6 +372,54 @@ void JS::MarkTaintedFunctionArguments(JSContext* cx, JSFunction* function, const } } +void JS::MaybeSpewStringTaint(JSContext* cx, JSString* str) { +//#ifdef JS_STRUCTURED_SPEW + if (!str || !str->taint()) { + return; + } + + AutoStructuredSpewer spew(cx, SpewChannel::TaintFlowSpewer, cx->currentScript()); + if (spew) { + spew->beginList(); + for (const TaintRange& range : str->taint()) { + spew->beginObject(); + spew->property("begin", range.begin()); + spew->property("end", range.end()); + + spew->beginListProperty("flow"); + for (TaintNode& node : range.flow()) { + const TaintOperation& op = node.operation(); + spew->beginObject(); + spew->property("operation", op.name()); + spew->boolProperty("builtin", op.is_native()); + spew->boolProperty("source", op.isSource()); + + const TaintLocation& loc = op.location(); + spew->beginObjectProperty("location"); + spew->property("filename", loc.filename().c_str(), loc.filename().size()); + spew->property("line", loc.line()); + spew->property("pos", loc.pos()); + spew->property("scriptline", loc.scriptStartLine()); + spew->property("scripthash", JS::convertDigestToHexString(loc.scriptHash()).c_str()); + spew->endObject(); // Location + + spew->beginListProperty("arguments"); + for (auto& arg : op.arguments()) { + spew->string(arg.c_str(), arg.size()); + } + spew->endList(); + + spew->endObject(); // Operation + } + spew->endList(); // flow + spew->endObject(); // range + } + spew->endList(); + + } +//#endif +} + // Print a message to stdout. void JS::TaintFoxReport(JSContext* cx, const char* msg) { diff --git a/js/src/jstaint.h b/js/src/jstaint.h index 767f48c302850..a3e45003ac99b 100644 --- a/js/src/jstaint.h +++ b/js/src/jstaint.h @@ -85,6 +85,9 @@ TaintOperation TaintOperationFromContext(JSContext* cx, const char* name, bool i // This is mainly useful for tracing tainted arguments through the code. void MarkTaintedFunctionArguments(JSContext* cx, JSFunction* function, const JS::CallArgs& args); +// Write the taint report to file +void MaybeSpewStringTaint(JSContext* cx, JSString* str); + // Print a message to stdout. void TaintFoxReport(JSContext* cx, const char* msg); diff --git a/js/src/util/StructuredSpewer.h b/js/src/util/StructuredSpewer.h index 613ef65b59ae7..46d4daeba1be3 100644 --- a/js/src/util/StructuredSpewer.h +++ b/js/src/util/StructuredSpewer.h @@ -73,7 +73,8 @@ namespace js { # define STRUCTURED_CHANNEL_LIST(_) \ _(BaselineICStats) \ - _(CacheIRHealthReport) + _(CacheIRHealthReport) \ + _(TaintFlowSpewer) // Structured spew channels enum class SpewChannel { diff --git a/js/src/vm/JSONPrinter.cpp b/js/src/vm/JSONPrinter.cpp index 5b5183d9fb7c5..6f93054b06e83 100644 --- a/js/src/vm/JSONPrinter.cpp +++ b/js/src/vm/JSONPrinter.cpp @@ -143,6 +143,17 @@ void JSONPrinter::property(const char* name, const char* value) { endStringProperty(); } +void JSONPrinter::property(const char* name, const char16_t* value, size_t length) { + beginStringProperty(name); + JSONString(out_, value, length); + endStringProperty(); +} + +void JSONPrinter::string(const char16_t* value, size_t length) { + JSONString(beginString(), value, length); + endString(); +} + void JSONPrinter::formatProperty(const char* name, const char* format, ...) { va_list ap; va_start(ap, format); diff --git a/js/src/vm/JSONPrinter.h b/js/src/vm/JSONPrinter.h index b90696a2b448f..06a16e4c2b662 100644 --- a/js/src/vm/JSONPrinter.h +++ b/js/src/vm/JSONPrinter.h @@ -49,6 +49,7 @@ class JSONPrinter { void property(const char* name, JSLinearString* value); void property(const char* name, const char* value); + void property(const char* name, const char16_t* value, size_t length); void property(const char* name, int32_t value); void property(const char* name, uint32_t value); void property(const char* name, int64_t value); @@ -60,6 +61,8 @@ class JSONPrinter { void property(const char* name, size_t value); #endif + void string(const char16_t* value, size_t length); + void formatProperty(const char* name, const char* format, ...) MOZ_FORMAT_PRINTF(3, 4); void formatProperty(const char* name, const char* format, va_list ap);