Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TaintSpewer #242

Merged
merged 7 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions dom/base/NodeInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ void NodeInfo::GetPrefix(nsAString& aPrefix) const {

void NodeInfo::GetNamespaceURI(nsAString& aNameSpaceURI) const {
if (mInner.mNamespaceID > 0) {
if (!nsNameSpaceManager::GetInstance()) {
SetDOMStringToNull(aNameSpaceURI);
return;
}
leeN marked this conversation as resolved.
Show resolved Hide resolved
nsresult rv = nsNameSpaceManager::GetInstance()->GetNameSpaceURI(
mInner.mNamespaceID, aNameSpaceURI);
// How can we possibly end up with a bogus namespace ID here?
Expand Down
9 changes: 9 additions & 0 deletions js/moz.configure
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
19 changes: 18 additions & 1 deletion js/src/builtin/String.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ static bool str_encodeURI(JSContext* cx, unsigned argc, Value* vp);

static bool str_encodeURI_Component(JSContext* cx, unsigned argc, Value* vp);

static bool str_foxhound(JSContext* cx, unsigned argc, Value* vp);

/*
* Global string methods
*/
Expand Down Expand Up @@ -723,7 +725,7 @@ static const JSFunctionSpec string_functions[] = {
JS_FN("encodeURI", str_encodeURI, 1, JSPROP_RESOLVING),
JS_FN("decodeURIComponent", str_decodeURI_Component, 1, JSPROP_RESOLVING),
JS_FN("encodeURIComponent", str_encodeURI_Component, 1, JSPROP_RESOLVING),

JS_FN("foxhound", str_foxhound, 1, JSPROP_RESOLVING),
JS_FS_END,
};

Expand Down Expand Up @@ -5325,6 +5327,21 @@ JSString* js::EncodeURI(JSContext* cx, const char* chars, size_t length) {
return sb.finishString();
}

static bool str_foxhound(JSContext* cx, unsigned argc, Value* vp) {
AutoJSMethodProfilerEntry pseudoFrame(cx, "foxhound");
CallArgs args = CallArgsFromVp(argc, vp);
// This will also do conversions from numbers to strings
Rooted<JSLinearString*> str(cx, ArgToLinearString(cx, args, 0));
if (!str) {
return false;
}

MaybeSpewMessage(cx, str);

args.rval().setUndefined();
return true;
}

static bool FlatStringMatchHelper(JSContext* cx, HandleString str,
HandleString pattern, bool* isFlat,
int32_t* match) {
Expand Down
2 changes: 2 additions & 0 deletions js/src/jsapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
78 changes: 78 additions & 0 deletions js/src/jstaint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -371,6 +372,83 @@ 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) {
JSLinearString* linear = str->ensureLinear(cx);
if (linear) {
spew->property("str", linear);
} else {
spew->property("str", "Non-linear String!");
}

spew->beginListProperty("taint");
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
}

void JS::MaybeSpewMessage(JSContext* cx, JSString* str) {
// First print message to stderr
SEprinter p;
p.put("!!! foxhound() called with message: ");
p.putString(cx, str);
p.put("\n");
p.flush();

#ifdef JS_STRUCTURED_SPEW
// Spew to file if enabled
AutoStructuredSpewer spew(cx, SpewChannel::TaintFlowSpewer, cx->currentScript());
if (spew) {
JSLinearString* linear = str->ensureLinear(cx);
if (linear) {
spew->property("foxhound", linear);
} else {
spew->property("foxhound", "Non-linear String!");
leeN marked this conversation as resolved.
Show resolved Hide resolved
}
}
#endif
}

// Print a message to stdout.
void JS::TaintFoxReport(JSContext* cx, const char* msg)
{
Expand Down
5 changes: 5 additions & 0 deletions js/src/jstaint.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ 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);
// Write a message to the file
void MaybeSpewMessage(JSContext* cx, JSString* str);

// Print a message to stdout.
void TaintFoxReport(JSContext* cx, const char* msg);

Expand Down
3 changes: 2 additions & 1 deletion js/src/util/StructuredSpewer.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ namespace js {

# define STRUCTURED_CHANNEL_LIST(_) \
_(BaselineICStats) \
_(CacheIRHealthReport)
_(CacheIRHealthReport) \
_(TaintFlowSpewer)

// Structured spew channels
enum class SpewChannel {
Expand Down
12 changes: 12 additions & 0 deletions js/src/vm/JSONPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,18 @@ 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();
first_ = false;
}

void JSONPrinter::formatProperty(const char* name, const char* format, ...) {
va_list ap;
va_start(ap, format);
Expand Down
3 changes: 3 additions & 0 deletions js/src/vm/JSONPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
Loading