Bug 1418246 - Return valid columnNumber value in CSP violation events, r=ckerschb

This commit is contained in:
Andrea Marchesini 2018-07-05 08:21:04 +02:00
parent 17578086c0
commit 14d462eeb3
37 changed files with 209 additions and 71 deletions

View File

@ -496,10 +496,12 @@ nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
if (reportViolation) {
nsAutoString fileName;
unsigned lineNum = 0;
unsigned columnNum = 0;
NS_NAMED_LITERAL_STRING(scriptSample, "call to eval() or related function blocked by CSP");
JS::AutoFilename scriptFilename;
if (JS::DescribeScriptedCaller(cx, &scriptFilename, &lineNum)) {
if (JS::DescribeScriptedCaller(cx, &scriptFilename, &lineNum,
&columnNum)) {
if (const char *file = scriptFilename.get()) {
CopyUTF8toUTF16(nsDependentCString(file), fileName);
}
@ -510,6 +512,7 @@ nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
fileName,
scriptSample,
lineNum,
columnNum,
EmptyString(),
EmptyString());
}

View File

@ -11949,6 +11949,7 @@ nsIDocument::InlineScriptAllowedByCSP()
true, // aParserCreated
nullptr, // FIXME get script sample (bug 1314567)
0, // aLineNumber
0, // aColumnNumber
&allowsInlineScript);
NS_ENSURE_SUCCESS(rv, true);
}

View File

@ -202,6 +202,19 @@ public:
* was set
*/
virtual uint32_t GetLineNumber() = 0;
// This doesn't entirely belong here since they only make sense for
// some types of linking elements, but it's a better place than
// anywhere else.
virtual void SetColumnNumber(uint32_t aColumnNumber) = 0;
/**
* Get the column number, as previously set by SetColumnNumber.
*
* @return the column number of this element; or 1 if no column number
* was set
*/
virtual uint32_t GetColumnNumber() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIStyleSheetLinkingElement,

View File

@ -198,13 +198,15 @@ CheckCSPForEval(JSContext* aCx, nsGlobalWindowInner* aWindow, ErrorResult& aErro
// Get the calling location.
uint32_t lineNum = 0;
uint32_t columnNum = 0;
nsAutoString fileNameString;
if (!nsJSUtils::GetCallingLocation(aCx, fileNameString, &lineNum)) {
if (!nsJSUtils::GetCallingLocation(aCx, fileNameString, &lineNum,
&columnNum)) {
fileNameString.AssignLiteral("unknown");
}
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
fileNameString, scriptSample, lineNum,
fileNameString, scriptSample, lineNum, columnNum,
EmptyString(), EmptyString());
}

View File

@ -76,6 +76,7 @@ nsStyleLinkElement::nsStyleLinkElement()
: mDontLoadStyle(false)
, mUpdatesEnabled(true)
, mLineNumber(1)
, mColumnNumber(1)
{
}
@ -192,6 +193,18 @@ nsStyleLinkElement::GetLineNumber()
return mLineNumber;
}
/* virtual */ void
nsStyleLinkElement::SetColumnNumber(uint32_t aColumnNumber)
{
mColumnNumber = aColumnNumber;
}
/* virtual */ uint32_t
nsStyleLinkElement::GetColumnNumber()
{
return mColumnNumber;
}
static uint32_t ToLinkMask(const nsAString& aLink)
{
// Keep this in sync with sRelValues in HTMLLinkElement.cpp
@ -381,7 +394,8 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
thisContent->NodePrincipal(),
info->mTriggeringPrincipal,
doc->GetDocumentURI(),
mLineNumber, text, &rv)) {
mLineNumber, mColumnNumber, text,
&rv)) {
if (NS_FAILED(rv)) {
return Err(rv);
}

View File

@ -56,6 +56,8 @@ public:
void OverrideBaseURI(nsIURI* aNewBaseURI) override;
void SetLineNumber(uint32_t aLineNumber) override;
uint32_t GetLineNumber() override;
void SetColumnNumber(uint32_t aColumnNumber) override;
uint32_t GetColumnNumber() override;
enum RelValue {
ePREFETCH = 0x00000001,
@ -136,6 +138,7 @@ protected:
bool mDontLoadStyle;
bool mUpdatesEnabled;
uint32_t mLineNumber;
uint32_t mColumnNumber;
};
#endif /* nsStyleLinkElement_h___ */

View File

@ -210,7 +210,7 @@ nsStyledElement::ParseStyleAttribute(const nsAString& aValue,
if (!isNativeAnon &&
!nsStyleUtil::CSPAllowsInlineStyle(nullptr, NodePrincipal(),
aMaybeScriptedPrincipal,
doc->GetDocumentURI(), 0, aValue,
doc->GetDocumentURI(), 0, 0, aValue,
nullptr))
return;

View File

@ -884,6 +884,7 @@ EventListenerManager::SetEventHandler(nsAtom* aName,
true, // aParserCreated (true because attribute event handler)
sampleIString,
0, // aLineNumber
0, // aColumnNumber
&allowsInlineScript);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -231,7 +231,7 @@ HTMLScriptElement::FreezeExecutionAttrs(nsIDocument* aOwnerDoc)
NS_LITERAL_CSTRING("HTML"), OwnerDoc(),
nsContentUtils::eDOM_PROPERTIES, "ScriptSourceInvalidUri",
params, ArrayLength(params), nullptr,
EmptyString(), GetScriptLineNumber());
EmptyString(), GetScriptLineNumber(), GetScriptColumnNumber());
}
} else {
const char16_t* params[] = { u"src" };
@ -240,7 +240,7 @@ HTMLScriptElement::FreezeExecutionAttrs(nsIDocument* aOwnerDoc)
NS_LITERAL_CSTRING("HTML"), OwnerDoc(),
nsContentUtils::eDOM_PROPERTIES, "ScriptSourceEmpty",
params, ArrayLength(params), nullptr,
EmptyString(), GetScriptLineNumber());
EmptyString(), GetScriptLineNumber(), GetScriptColumnNumber());
}
// At this point mUri will be null for invalid URLs.

View File

@ -127,6 +127,8 @@ interface nsIContentSecurityPolicy : nsISerializable
* (and compare to the hashes listed in the policy)
* @param aLineNumber The line number of the inline resource
* (used for reporting)
* @param aColumnNumber The column number of the inline resource
* (used for reporting)
* @return
* Whether or not the effects of the inline style should be allowed
* (block the rules if false).
@ -135,7 +137,8 @@ interface nsIContentSecurityPolicy : nsISerializable
in AString aNonce,
in boolean aParserCreated,
in nsISupports aElementOrContent,
in unsigned long aLineNumber);
in unsigned long aLineNumber,
in unsigned long aColumnNumber);
/**
* whether this policy allows eval and eval-like functions
@ -175,6 +178,8 @@ interface nsIContentSecurityPolicy : nsISerializable
* sample of the violating content (to aid debugging)
* @param lineNum
* source line number of the violation (if available)
* @param columnNum
* source column number of the violation (if available)
* @param aNonce
* (optional) If this is a nonce violation, include the nonce so we can
* recheck to determine which policies were violated and send the
@ -189,6 +194,7 @@ interface nsIContentSecurityPolicy : nsISerializable
in AString sourceFile,
in AString scriptSample,
in int32_t lineNum,
in int32_t columnNum,
[optional] in AString nonce,
[optional] in AString content);

View File

@ -182,6 +182,7 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
true, // aParserCreated
nullptr, // aContent
0, // aLineNumber
0, // aColumnNumber
&allowsInlineScript);
//return early if inline scripts are not allowed

View File

@ -1225,6 +1225,7 @@ CSPAllowsInlineScript(nsIScriptElement* aElement, nsIDocument* aDocument)
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT,
nonce, parserCreated, aElement,
aElement->GetScriptLineNumber(),
aElement->GetScriptColumnNumber(),
&allowInlineScript);
return allowInlineScript;
}
@ -2868,10 +2869,11 @@ ScriptLoader::VerifySRI(ScriptLoadRequest* aRequest,
nsAutoCString violationURISpec;
mDocument->GetDocumentURI()->GetAsciiSpec(violationURISpec);
uint32_t lineNo = aRequest->mElement ? aRequest->mElement->GetScriptLineNumber() : 0;
uint32_t columnNo = aRequest->mElement ? aRequest->mElement->GetScriptColumnNumber() : 0;
csp->LogViolationDetails(
nsIContentSecurityPolicy::VIOLATION_TYPE_REQUIRE_SRI_FOR_SCRIPT,
NS_ConvertUTF8toUTF16(violationURISpec),
EmptyString(), lineNo, EmptyString(), EmptyString());
EmptyString(), lineNo, columnNo, EmptyString(), EmptyString());
rv = NS_ERROR_SRI_CORRUPT;
}
}
@ -2953,12 +2955,13 @@ ScriptLoader::ReportErrorToConsole(ScriptLoadRequest *aRequest,
const char16_t* params[] = { url.get() };
uint32_t lineNo = aRequest->mElement->GetScriptLineNumber();
uint32_t columnNo = aRequest->mElement->GetScriptColumnNumber();
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Script Loader"), mDocument,
nsContentUtils::eDOM_PROPERTIES, message,
params, ArrayLength(params), nullptr,
EmptyString(), lineNo);
EmptyString(), lineNo, columnNo);
}
void

View File

@ -32,6 +32,7 @@ public:
explicit nsIScriptElement(mozilla::dom::FromParser aFromParser)
: mLineNumber(1),
mColumnNumber(1),
mAlreadyStarted(false),
mMalformed(false),
mDoneAddingChildren(aFromParser == mozilla::dom::NOT_FROM_PARSER ||
@ -146,6 +147,16 @@ public:
return mLineNumber;
}
void SetScriptColumnNumber(uint32_t aColumnNumber)
{
mColumnNumber = aColumnNumber;
}
uint32_t GetScriptColumnNumber()
{
return mColumnNumber;
}
void SetIsMalformed()
{
mMalformed = true;
@ -297,6 +308,11 @@ protected:
*/
uint32_t mLineNumber;
/**
* The start column number of the script.
*/
uint32_t mColumnNumber;
/**
* The "already started" flag per HTML5.
*/

View File

@ -277,7 +277,8 @@ nsCSPContext::permitsInternal(CSPDirective aDir,
EmptyString(), /* no observer subject */
EmptyString(), /* no source file */
EmptyString(), /* no script sample */
0); /* no line number */
0, /* no line number */
0); /* no column number */
}
}
}
@ -457,7 +458,8 @@ nsCSPContext::reportInlineViolation(nsContentPolicyType aContentType,
const nsAString& aContent,
const nsAString& aViolatedDirective,
uint32_t aViolatedPolicyIndex, // TODO, use report only flag for that
uint32_t aLineNumber)
uint32_t aLineNumber,
uint32_t aColumnNumber)
{
nsString observerSubject;
// if the nonce is non empty, then we report the nonce error, otherwise
@ -499,7 +501,8 @@ nsCSPContext::reportInlineViolation(nsContentPolicyType aContentType,
observerSubject, // aObserverSubject
NS_ConvertUTF8toUTF16(sourceFile), // aSourceFile
codeSample, // aScriptSample
aLineNumber); // aLineNum
aLineNumber, // aLineNum
aColumnNumber); // aColumnNum
}
NS_IMETHODIMP
@ -508,6 +511,7 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
bool aParserCreated,
nsISupports* aElementOrContent,
uint32_t aLineNumber,
uint32_t aColumnNumber,
bool* outAllowsInline)
{
*outAllowsInline = true;
@ -565,7 +569,8 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
content,
violatedDirective,
i,
aLineNumber);
aLineNumber,
aColumnNumber);
}
}
return NS_OK;
@ -584,7 +589,8 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
* which is why we must check allows() again here.
*
* Note: This macro uses some parameters from its caller's context:
* p, mPolicies, this, aSourceFile, aScriptSample, aLineNum, selfISupports
* p, mPolicies, this, aSourceFile, aScriptSample, aLineNum, aColumnNum,
* selfISupports
*
* @param violationType: the VIOLATION_TYPE_* constant (partial symbol)
* such as INLINE_SCRIPT
@ -612,7 +618,8 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
violatedDirective); \
this->AsyncReportViolation(selfISupports, nullptr, violatedDirective, p, \
NS_LITERAL_STRING(observerTopic), \
aSourceFile, aScriptSample, aLineNum); \
aSourceFile, aScriptSample, aLineNum, \
aColumnNum); \
} \
PR_END_MACRO; \
break
@ -629,6 +636,8 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
* sample of the violating content (to aid debugging)
* @param aLineNum
* source line number of the violation (if available)
* @param aColumnNum
* source column number of the violation (if available)
* @param aNonce
* (optional) If this is a nonce violation, include the nonce so we can
* recheck to determine which policies were violated and send the
@ -644,6 +653,7 @@ nsCSPContext::LogViolationDetails(uint16_t aViolationType,
const nsAString& aSourceFile,
const nsAString& aScriptSample,
int32_t aLineNum,
int32_t aColumnNum,
const nsAString& aNonce,
const nsAString& aContent)
{
@ -860,6 +870,7 @@ nsCSPContext::GatherSecurityPolicyViolationEventData(
nsAString& aSourceFile,
nsAString& aScriptSample,
uint32_t aLineNum,
uint32_t aColumnNum,
mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit)
{
NS_ENSURE_ARG_MAX(aViolatedPolicyIndex, mPolicies.Length() - 1);
@ -940,8 +951,7 @@ nsCSPContext::GatherSecurityPolicyViolationEventData(
aViolationEventInit.mLineNumber = aLineNum;
// column-number
// TODO: Set correct column number.
aViolationEventInit.mColumnNumber = 0;
aViolationEventInit.mColumnNumber = aColumnNum;
aViolationEventInit.mBubbles = true;
aViolationEventInit.mComposed = true;
@ -991,6 +1001,11 @@ nsCSPContext::SendReports(
report.mCsp_report.mLine_number.Value() = aViolationEventInit.mLineNumber;
}
if (aViolationEventInit.mLineNumber != 0) {
report.mCsp_report.mColumn_number.Construct();
report.mCsp_report.mColumn_number.Value() = aViolationEventInit.mColumnNumber;
}
nsString csp_report;
if (!report.ToJSON(csp_report)) {
return NS_ERROR_FAILURE;
@ -1016,7 +1031,9 @@ nsCSPContext::SendReports(
reportURICstring.get()));
logToConsole("triedToSendReport", params, ArrayLength(params),
aViolationEventInit.mSourceFile, aViolationEventInit.mSample,
aViolationEventInit.mLineNumber, 0, nsIScriptError::errorFlag);
aViolationEventInit.mLineNumber,
aViolationEventInit.mColumnNumber,
nsIScriptError::errorFlag);
continue; // don't return yet, there may be more URIs
}
@ -1060,7 +1077,9 @@ nsCSPContext::SendReports(
const char16_t* params[] = { reportURIs[r].get() };
logToConsole("reportURInotHttpsOrHttp2", params, ArrayLength(params),
aViolationEventInit.mSourceFile, aViolationEventInit.mSample,
aViolationEventInit.mLineNumber, 0, nsIScriptError::errorFlag);
aViolationEventInit.mLineNumber,
aViolationEventInit.mColumnNumber,
nsIScriptError::errorFlag);
continue;
}
@ -1126,7 +1145,9 @@ nsCSPContext::SendReports(
CSPCONTEXTLOG(("AsyncOpen failed for report URI %s", NS_ConvertUTF16toUTF8(params[0]).get()));
logToConsole("triedToSendReport", params, ArrayLength(params),
aViolationEventInit.mSourceFile, aViolationEventInit.mSample,
aViolationEventInit.mLineNumber, 0, nsIScriptError::errorFlag);
aViolationEventInit.mLineNumber,
aViolationEventInit.mColumnNumber,
nsIScriptError::errorFlag);
} else {
CSPCONTEXTLOG(("Sent violation report to URI %s", reportURICstring.get()));
}
@ -1174,6 +1195,7 @@ class CSPReportSenderRunnable final : public Runnable
const nsAString& aSourceFile,
const nsAString& aScriptSample,
uint32_t aLineNum,
uint32_t aColumnNum,
nsCSPContext* aCSPContext)
: mozilla::Runnable("CSPReportSenderRunnable")
, mBlockedContentSource(aBlockedContentSource)
@ -1184,6 +1206,7 @@ class CSPReportSenderRunnable final : public Runnable
, mSourceFile(aSourceFile)
, mScriptSample(aScriptSample)
, mLineNum(aLineNum)
, mColumnNum(aColumnNum)
, mCSPContext(aCSPContext)
{
NS_ASSERTION(!aViolatedDirective.IsEmpty(), "Can not send reports without a violated directive");
@ -1214,7 +1237,7 @@ class CSPReportSenderRunnable final : public Runnable
rv = mCSPContext->GatherSecurityPolicyViolationEventData(
blockedURI, mOriginalURI,
mViolatedDirective, mViolatedPolicyIndex,
mSourceFile, mScriptSample, mLineNum,
mSourceFile, mScriptSample, mLineNum, mColumnNum,
init);
NS_ENSURE_SUCCESS(rv, rv);
@ -1222,8 +1245,8 @@ class CSPReportSenderRunnable final : public Runnable
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
NS_ASSERTION(observerService, "needs observer service");
rv = observerService->NotifyObservers(mObserverSubject,
CSP_VIOLATION_TOPIC,
mViolatedDirective.get());
CSP_VIOLATION_TOPIC,
mViolatedDirective.get());
NS_ENSURE_SUCCESS(rv, rv);
// 2) send reports for the policy that was violated
@ -1256,7 +1279,7 @@ class CSPReportSenderRunnable final : public Runnable
mCSPContext->logToConsole(mReportOnlyFlag ? "CSPROViolationWithURI" :
"CSPViolationWithURI",
params, ArrayLength(params), mSourceFile, mScriptSample,
mLineNum, 0, nsIScriptError::errorFlag);
mLineNum, mColumnNum, nsIScriptError::errorFlag);
}
// 4) fire violation event
@ -1275,6 +1298,7 @@ class CSPReportSenderRunnable final : public Runnable
nsString mSourceFile;
nsString mScriptSample;
uint32_t mLineNum;
uint32_t mColumnNum;
RefPtr<nsCSPContext> mCSPContext;
};
@ -1302,6 +1326,8 @@ class CSPReportSenderRunnable final : public Runnable
* a sample of the violating inline script
* @param aLineNum
* source line number of the violation (if available)
* @param aColumnNum
* source column number of the violation (if available)
*/
nsresult
nsCSPContext::AsyncReportViolation(nsISupports* aBlockedContentSource,
@ -1311,7 +1337,8 @@ nsCSPContext::AsyncReportViolation(nsISupports* aBlockedContentSource,
const nsAString& aObserverSubject,
const nsAString& aSourceFile,
const nsAString& aScriptSample,
uint32_t aLineNum)
uint32_t aLineNum,
uint32_t aColumnNum)
{
NS_ENSURE_ARG_MAX(aViolatedPolicyIndex, mPolicies.Length() - 1);
@ -1325,6 +1352,7 @@ nsCSPContext::AsyncReportViolation(nsISupports* aBlockedContentSource,
aSourceFile,
aScriptSample,
aLineNum,
aColumnNum,
this);
if (XRE_IsContentProcess()) {

View File

@ -76,6 +76,8 @@ class nsCSPContext : public nsIContentSecurityPolicy
* a sample of the violating inline script
* @param aLineNum
* source line number of the violation (if available)
* @param aColumnNum
* source column number of the violation (if available)
* @param aViolationEventInit
* The output
*/
@ -87,6 +89,7 @@ class nsCSPContext : public nsIContentSecurityPolicy
nsAString& aSourceFile,
nsAString& aScriptSample,
uint32_t aLineNum,
uint32_t aColumnNum,
mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit);
nsresult SendReports(
@ -103,7 +106,8 @@ class nsCSPContext : public nsIContentSecurityPolicy
const nsAString& aObserverSubject,
const nsAString& aSourceFile,
const nsAString& aScriptSample,
uint32_t aLineNum);
uint32_t aLineNum,
uint32_t aColumnNum);
// Hands off! Don't call this method unless you know what you
// are doing. It's only supposed to be called from within
@ -134,7 +138,8 @@ class nsCSPContext : public nsIContentSecurityPolicy
const nsAString& aContent,
const nsAString& aViolatedDirective,
uint32_t aViolatedPolicyIndex,
uint32_t aLineNumber);
uint32_t aLineNumber,
uint32_t aColumnNumber);
static int32_t sScriptSampleMaxLength;

View File

@ -113,7 +113,8 @@ function run_test() {
"", // aNonce
false, // aParserCreated
content, // aContent
0); // aLineNumber
0, // aLineNumber
0); // aColumnNumber
// this is not a report only policy, so it better block inline scripts
Assert.ok(!inlineOK);
@ -122,7 +123,9 @@ function run_test() {
// test that eval violations cause a report.
makeTest(1, {"blocked-uri": "",
// JSON script-sample is UTF8 encoded
"script-sample" : "\xc2\xa3\xc2\xa5\xc2\xb5\xe5\x8c\x97\xf0\xa0\x9d\xb9"}, false,
"script-sample" : "\xc2\xa3\xc2\xa5\xc2\xb5\xe5\x8c\x97\xf0\xa0\x9d\xb9",
"line-number": 1,
"column-number": 2}, false,
function(csp) {
let evalOK = true, oReportViolation = {'value': false};
evalOK = csp.getAllowsEval(oReportViolation);
@ -140,7 +143,8 @@ function run_test() {
// csp report in JSON is not cut-off, please
// note that JSON is UTF8 encoded.
"\u00a3\u00a5\u00b5\u5317\ud841\udf79",
1);
1, // line number
2); // column number
}
});
@ -163,7 +167,8 @@ function run_test() {
"", // aNonce
false, // aParserCreated
content, // aContent
0); // aLineNumber
0, // aLineNumber
0); // aColumnNumber
// this is a report only policy, so it better allow inline scripts
Assert.ok(inlineOK);
@ -185,7 +190,8 @@ function run_test() {
csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT,
selfuri.asciiSpec,
"script sample",
4);
4, // line number
5); // column number
}
});

View File

@ -523,7 +523,7 @@ nsSMILCSSValueType::ValueFromString(nsCSSPropertyID aPropID,
doc->NodePrincipal(),
nullptr,
doc->GetDocumentURI(),
0, aString, nullptr)) {
0, 0, aString, nullptr)) {
return;
}
@ -567,7 +567,8 @@ nsSMILCSSValueType::ValueFromAnimationValue(nsCSSPropertyID aPropID,
doc->NodePrincipal(),
nullptr,
doc->GetDocumentURI(),
0, kPlaceholderText, nullptr)) {
0, 0, kPlaceholderText,
nullptr)) {
return result;
}

View File

@ -168,7 +168,7 @@ SVGScriptElement::FreezeExecutionAttrs(nsIDocument* aOwnerDoc)
NS_LITERAL_CSTRING("SVG"), OwnerDoc(),
nsContentUtils::eDOM_PROPERTIES, "ScriptSourceInvalidUri",
params, ArrayLength(params), nullptr,
EmptyString(), GetScriptLineNumber());
EmptyString(), GetScriptLineNumber(), GetScriptColumnNumber());
}
} else {
const char16_t* params[] = { isHref ? u"href" : u"xlink:href" };
@ -177,7 +177,7 @@ SVGScriptElement::FreezeExecutionAttrs(nsIDocument* aOwnerDoc)
NS_LITERAL_CSTRING("SVG"), OwnerDoc(),
nsContentUtils::eDOM_PROPERTIES, "ScriptSourceEmpty",
params, ArrayLength(params), nullptr,
EmptyString(), GetScriptLineNumber());
EmptyString(), GetScriptLineNumber(), GetScriptColumnNumber());
}
// At this point mUri will be null for invalid URLs.

View File

@ -16,6 +16,7 @@ dictionary CSPReportProperties {
DOMString source-file;
DOMString script-sample;
long line-number;
long column-number;
};
dictionary CSPReport {

View File

@ -584,14 +584,18 @@ class LogViolationDetailsRunnable final : public WorkerMainThreadRunnable
{
nsString mFileName;
uint32_t mLineNum;
uint32_t mColumnNum;
public:
LogViolationDetailsRunnable(WorkerPrivate* aWorker,
const nsString& aFileName,
uint32_t aLineNum)
uint32_t aLineNum,
uint32_t aColumnNum)
: WorkerMainThreadRunnable(aWorker,
NS_LITERAL_CSTRING("RuntimeService :: LogViolationDetails"))
, mFileName(aFileName), mLineNum(aLineNum)
, mFileName(aFileName)
, mLineNum(aLineNum)
, mColumnNum(aColumnNum)
{
MOZ_ASSERT(aWorker);
}
@ -611,16 +615,17 @@ ContentSecurityPolicyAllows(JSContext* aCx)
if (worker->GetReportCSPViolations()) {
nsString fileName;
uint32_t lineNum = 0;
uint32_t columnNum = 0;
JS::AutoFilename file;
if (JS::DescribeScriptedCaller(aCx, &file, &lineNum) && file.get()) {
if (JS::DescribeScriptedCaller(aCx, &file, &lineNum, &columnNum) && file.get()) {
fileName = NS_ConvertUTF8toUTF16(file.get());
} else {
MOZ_ASSERT(!JS_IsExceptionPending(aCx));
}
RefPtr<LogViolationDetailsRunnable> runnable =
new LogViolationDetailsRunnable(worker, fileName, lineNum);
new LogViolationDetailsRunnable(worker, fileName, lineNum, columnNum);
ErrorResult rv;
runnable->Dispatch(Killing, rv);
@ -2620,7 +2625,7 @@ LogViolationDetailsRunnable::MainThreadRun()
"Call to eval() or related function blocked by CSP.");
if (mWorkerPrivate->GetReportCSPViolations()) {
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
mFileName, scriptSample, mLineNum,
mFileName, scriptSample, mLineNum, mColumnNum,
EmptyString(), EmptyString());
}
}

View File

@ -1226,7 +1226,7 @@ private:
if (wcsp) {
wcsp->LogViolationDetails(
nsIContentSecurityPolicy::VIOLATION_TYPE_REQUIRE_SRI_FOR_SCRIPT,
aLoadInfo.mURL, EmptyString(), 0, EmptyString(), EmptyString());
aLoadInfo.mURL, EmptyString(), 0, 0, EmptyString(), EmptyString());
}
return NS_ERROR_SRI_CORRUPT;
}

View File

@ -247,10 +247,11 @@ NS_IMETHODIMP
nsXBLContentSink::HandleStartElement(const char16_t *aName,
const char16_t **aAtts,
uint32_t aAttsCount,
uint32_t aLineNumber)
uint32_t aLineNumber,
uint32_t aColumnNumber)
{
nsresult rv = nsXMLContentSink::HandleStartElement(aName, aAtts, aAttsCount,
aLineNumber);
aLineNumber, aColumnNumber);
if (NS_FAILED(rv))
return rv;
@ -850,7 +851,8 @@ nsXBLContentSink::ConstructParameter(const char16_t **aAtts)
nsresult
nsXBLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
mozilla::dom::NodeInfo* aNodeInfo,
uint32_t aLineNumber, uint32_t aColumnNumber,
nsIContent** aResult, bool* aAppendContent,
FromParser aFromParser)
{
@ -858,7 +860,7 @@ nsXBLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
if (!aNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) {
#endif
return nsXMLContentSink::CreateElement(aAtts, aAttsCount, aNodeInfo,
aLineNumber, aResult,
aLineNumber, aColumnNumber, aResult,
aAppendContent, aFromParser);
#ifdef MOZ_XUL
}

View File

@ -68,7 +68,8 @@ public:
NS_IMETHOD HandleStartElement(const char16_t *aName,
const char16_t **aAtts,
uint32_t aAttsCount,
uint32_t aLineNumber) override;
uint32_t aLineNumber,
uint32_t aColumnNumber) override;
NS_IMETHOD HandleEndElement(const char16_t *aName) override;
@ -88,7 +89,8 @@ protected:
bool NotifyForDocElement() override { return false; }
nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
mozilla::dom::NodeInfo* aNodeInfo,
uint32_t aLineNumber, uint32_t aColumnNumber,
nsIContent** aResult, bool* aAppendContent,
mozilla::dom::FromParser aFromParser) override;

View File

@ -481,7 +481,8 @@ FindIsAttrValue(const char16_t** aAtts, const char16_t** aResult)
nsresult
nsXMLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
mozilla::dom::NodeInfo* aNodeInfo,
uint32_t aLineNumber, uint32_t aColumnNumber,
nsIContent** aResult, bool* aAppendContent,
FromParser aFromParser)
{
@ -512,6 +513,7 @@ nsXMLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(content);
if (sele) {
sele->SetScriptLineNumber(aLineNumber);
sele->SetScriptColumnNumber(aColumnNumber);
sele->SetCreatorParser(GetParser());
} else {
MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, "Node didn't QI to script, but SVG wasn't disabled.");
@ -549,6 +551,7 @@ nsXMLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
}
if (!aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML)) {
ssle->SetLineNumber(aFromParser ? aLineNumber : 0);
ssle->SetColumnNumber(aFromParser ? aColumnNumber : 0);
}
}
}
@ -988,10 +991,11 @@ NS_IMETHODIMP
nsXMLContentSink::HandleStartElement(const char16_t *aName,
const char16_t **aAtts,
uint32_t aAttsCount,
uint32_t aLineNumber)
uint32_t aLineNumber,
uint32_t aColumnNumber)
{
return HandleStartElement(aName, aAtts, aAttsCount, aLineNumber,
true);
aColumnNumber, true);
}
nsresult
@ -999,6 +1003,7 @@ nsXMLContentSink::HandleStartElement(const char16_t *aName,
const char16_t **aAtts,
uint32_t aAttsCount,
uint32_t aLineNumber,
uint32_t aColumnNumber,
bool aInterruptable)
{
MOZ_ASSERT(aAttsCount % 2 == 0, "incorrect aAttsCount");
@ -1033,7 +1038,7 @@ nsXMLContentSink::HandleStartElement(const char16_t *aName,
nsINode::ELEMENT_NODE);
result = CreateElement(aAtts, aAttsCount, nodeInfo, aLineNumber,
getter_AddRefs(content), &appendContent,
aColumnNumber, getter_AddRefs(content), &appendContent,
FROM_PARSER_NETWORK);
NS_ENSURE_SUCCESS(result, result);

View File

@ -117,7 +117,8 @@ protected:
nsIContent *aContent);
virtual bool NotifyForDocElement() { return true; }
virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
mozilla::dom::NodeInfo* aNodeInfo,
uint32_t aLineNumber, uint32_t aColumnNumber,
nsIContent** aResult, bool* aAppendContent,
mozilla::dom::FromParser aFromParser);
@ -181,7 +182,7 @@ protected:
nsresult HandleStartElement(const char16_t *aName, const char16_t **aAtts,
uint32_t aAttsCount, uint32_t aLineNumber,
bool aInterruptable);
uint32_t aColumnNumber, bool aInterruptable);
nsresult HandleEndElement(const char16_t *aName, bool aInterruptable);
nsresult HandleCharacterData(const char16_t *aData, uint32_t aLength,
bool aInterruptable);

View File

@ -82,7 +82,8 @@ protected:
nsAtom* aTagName,
nsIContent* aContent) override;
virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
mozilla::dom::NodeInfo* aNodeInfo,
uint32_t aLineNumber, uint32_t aColumnNumber,
nsIContent** aResult, bool* aAppendContent,
mozilla::dom::FromParser aFromParser) override;
virtual nsresult CloseElement(nsIContent* aContent) override;
@ -208,7 +209,8 @@ nsXMLFragmentContentSink::SetDocElement(int32_t aNameSpaceID,
nsresult
nsXMLFragmentContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
mozilla::dom::NodeInfo* aNodeInfo,
uint32_t aLineNumber, uint32_t aColumnNumber,
nsIContent** aResult, bool* aAppendContent,
FromParser /*aFromParser*/)
{
@ -216,6 +218,7 @@ nsXMLFragmentContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCo
// fancy CloseElement stuff.
nsresult rv = nsXMLContentSink::CreateElement(aAtts, aAttsCount,
aNodeInfo, aLineNumber,
aColumnNumber,
aResult, aAppendContent,
NOT_FROM_PARSER);

View File

@ -121,7 +121,8 @@ NS_IMETHODIMP
txStylesheetSink::HandleStartElement(const char16_t *aName,
const char16_t **aAtts,
uint32_t aAttsCount,
uint32_t aLineNumber)
uint32_t aLineNumber,
uint32_t aColumnNumber)
{
MOZ_ASSERT(aAttsCount % 2 == 0, "incorrect aAttsCount");

View File

@ -407,7 +407,8 @@ NS_IMETHODIMP
XULContentSinkImpl::HandleStartElement(const char16_t *aName,
const char16_t **aAtts,
uint32_t aAttsCount,
uint32_t aLineNumber)
uint32_t aLineNumber,
uint32_t aColumnNumber)
{
// XXX Hopefully the parser will flag this before we get here. If
// we're in the epilog, there should be no new elements
@ -666,7 +667,7 @@ XULContentSinkImpl::ReportError(const char16_t* aErrorText,
parsererror.Append((char16_t)0xFFFF);
parsererror.AppendLiteral("parsererror");
rv = HandleStartElement(parsererror.get(), noAtts, 0, 0);
rv = HandleStartElement(parsererror.get(), noAtts, 0, 0, 0);
NS_ENSURE_SUCCESS(rv,rv);
rv = HandleCharacterData(aErrorText, NS_strlen(aErrorText));
@ -676,7 +677,7 @@ XULContentSinkImpl::ReportError(const char16_t* aErrorText,
sourcetext.Append((char16_t)0xFFFF);
sourcetext.AppendLiteral("sourcetext");
rv = HandleStartElement(sourcetext.get(), noAtts, 0, 0);
rv = HandleStartElement(sourcetext.get(), noAtts, 0, 0, 0);
NS_ENSURE_SUCCESS(rv,rv);
rv = HandleCharacterData(aSourceText, NS_strlen(aSourceText));

View File

@ -785,7 +785,7 @@ SheetLoadData::VerifySheetReadyToParse(nsresult aStatus,
csp->LogViolationDetails(
nsIContentSecurityPolicy::VIOLATION_TYPE_REQUIRE_SRI_FOR_STYLE,
NS_ConvertUTF8toUTF16(spec), EmptyString(),
0, EmptyString(), EmptyString());
0, 0, EmptyString(), EmptyString());
return NS_OK;
}
} else {

View File

@ -773,6 +773,7 @@ nsStyleUtil::CSPAllowsInlineStyle(Element* aElement,
nsIPrincipal* aTriggeringPrincipal,
nsIURI* aSourceURI,
uint32_t aLineNumber,
uint32_t aColumnNumber,
const nsAString& aStyleText,
nsresult* aRv)
{
@ -821,7 +822,7 @@ nsStyleUtil::CSPAllowsInlineStyle(Element* aElement,
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_STYLESHEET,
nonce,
false, // aParserCreated only applies to scripts
styleText, aLineNumber,
styleText, aLineNumber, aColumnNumber,
&allowInlineStyle);
NS_ENSURE_SUCCESS(rv, false);

View File

@ -202,6 +202,9 @@ public:
* @param aLineNumber
* Line number of inline style element in the containing document (for
* reporting violations)
* @param aColumnNumber
* Column number of inline style element in the containing document (for
* reporting violations)
* @param aStyleText
* Contents of the inline style element (for reporting violations)
* @param aRv
@ -214,6 +217,7 @@ public:
nsIPrincipal* aTriggeringPrincipal,
nsIURI* aSourceURI,
uint32_t aLineNumber,
uint32_t aColumnNumber,
const nsAString& aStyleText,
nsresult* aRv);

View File

@ -322,7 +322,8 @@ nsExpatDriver::HandleStartElement(const char16_t *aValue,
if (mSink) {
nsresult rv = mSink->
HandleStartElement(aValue, aAtts, attrArrayLength,
XML_GetCurrentLineNumber(mExpatParser));
XML_GetCurrentLineNumber(mExpatParser),
XML_GetCurrentColumnNumber(mExpatParser));
MaybeStopParser(rv);
}

View File

@ -28,11 +28,13 @@ interface nsIExpatSink : nsISupports
* present in aAtts.
* @param aAttsCount the number of elements in aAtts.
* @param aLineNumber the line number of the start tag in the data stream.
* @param aColumnNumber the column number of the start tag in the data stream.
*/
void HandleStartElement(in wstring aName,
[array, size_is(aAttsCount)] in wstring aAtts,
in unsigned long aAttsCount,
in unsigned long aLineNumber);
in unsigned long aLineNumber,
in unsigned long aColumnNumber);
/**
* Called to handle the closing tag of an element.

View File

@ -79,7 +79,8 @@ NS_IMETHODIMP
nsSAXXMLReader::HandleStartElement(const char16_t *aName,
const char16_t **aAtts,
uint32_t aAttsCount,
uint32_t aLineNumber)
uint32_t aLineNumber,
uint32_t aColumnNumber)
{
if (!mContentHandler)
return NS_OK;

View File

@ -7,7 +7,8 @@
var watcher = new EventWatcher(t, document, 'securitypolicyviolation');
watcher.wait_for('securitypolicyviolation').then(t.step_func_done(e => {
assert_equals(e.blockedURI, "eval");
assert_equals(e.lineNumber, 14);
assert_equals(e.lineNumber, 15);
assert_equals(e.columnNumber, 12);
}));
try {

View File

@ -7,7 +7,8 @@
var watcher = new EventWatcher(t, document, 'securitypolicyviolation');
watcher.wait_for('securitypolicyviolation').then(t.step_func_done(e => {
assert_equals(e.blockedURI, "inline");
assert_equals(e.lineNumber, 14);
assert_equals(e.lineNumber, 15);
assert_equals(e.columnNumber, 1);
}));
}, "Inline violations have a blockedURI of 'inline'");
</script>

View File

@ -35,19 +35,22 @@
}))
.then(t.step_func(e => {
assert_equals(e.blockedURI, "inline");
assert_equals(e.lineNumber, 132);
assert_equals(e.lineNumber, 135);
assert_equals(e.columnNumber, 7);
assert_equals(e.target, document, "Disconnected elements target the document");
return watcher.wait_for('securitypolicyviolation');
}))
.then(t.step_func(e => {
assert_equals(e.blockedURI, "inline");
assert_equals(e.lineNumber, 143);
assert_equals(e.lineNumber, 146);
assert_equals(e.columnNumber, 7);
assert_equals(e.target, document, "Elements disconnected after triggering target the document.");
return watcher.wait_for('securitypolicyviolation');
}))
.then(t.step_func(e => {
assert_equals(e.blockedURI, "inline");
assert_equals(e.lineNumber, 157);
assert_equals(e.lineNumber, 160);
assert_equals(e.columnNumber, 7);
assert_equals(e.target, document, "Elements in DocumentFragments target the document");
}))
.then(t.step_func_done(_ => {