diff --git a/caps/nsScriptSecurityManager.cpp b/caps/nsScriptSecurityManager.cpp index 8f36fa9171..e7dedba8fa 100644 --- a/caps/nsScriptSecurityManager.cpp +++ b/caps/nsScriptSecurityManager.cpp @@ -535,7 +535,8 @@ NS_IMPL_ISUPPORTS(nsScriptSecurityManager, ///////////////// Security Checks ///////////////// bool -nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx) +nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx, + JS::HandleValue aValue) { MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext()); nsCOMPtr subjectPrincipal = nsContentUtils::SubjectPrincipal(); @@ -558,12 +559,23 @@ nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx) } if (reportViolation) { - nsAutoString fileName; - unsigned lineNum = 0; - NS_NAMED_LITERAL_STRING(scriptSample, "call to eval() or related function blocked by CSP"); + JS::Rooted jsString(cx, JS::ToString(cx, aValue)); + if (NS_WARN_IF(!jsString)) { + JS_ClearPendingException(cx); + return false; + } + + nsAutoJSString scriptSample; + if (NS_WARN_IF(!scriptSample.init(cx, jsString))) { + JS_ClearPendingException(cx); + return false; + } JS::AutoFilename scriptFilename; - if (JS::DescribeScriptedCaller(cx, &scriptFilename, &lineNum)) { + nsAutoString fileName; + unsigned lineNum = 0; + unsigned columnNum = 0; + if (JS::DescribeScriptedCaller(cx, &scriptFilename, &lineNum, &columnNum)) { if (const char *file = scriptFilename.get()) { CopyUTF8toUTF16(nsDependentCString(file), fileName); } @@ -574,6 +586,7 @@ nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx) fileName, scriptSample, lineNum, + columnNum, EmptyString(), EmptyString()); } diff --git a/caps/nsScriptSecurityManager.h b/caps/nsScriptSecurityManager.h index c5a1e5cd28..b1953291db 100644 --- a/caps/nsScriptSecurityManager.h +++ b/caps/nsScriptSecurityManager.h @@ -91,7 +91,7 @@ private: // Decides, based on CSP, whether or not eval() and stuff can be executed. static bool - ContentSecurityPolicyPermitsJSAction(JSContext *cx); + ContentSecurityPolicyPermitsJSAction(JSContext *cx, JS::HandleValue aValue); static bool JSPrincipalsSubsume(JSPrincipals *first, JSPrincipals *second); diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 4d3fc70b83..ab9f2419a1 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -11910,6 +11910,7 @@ nsIDocument::InlineScriptAllowedByCSP() true, // aParserCreated EmptyString(), // FIXME get script sample (bug 1314567) 0, // aLineNumber + 0, // aColumnNumber &allowsInlineScript); NS_ENSURE_SUCCESS(rv, true); } diff --git a/dom/base/nsIStyleSheetLinkingElement.h b/dom/base/nsIStyleSheetLinkingElement.h index 614005640b..0bf3b5827f 100644 --- a/dom/base/nsIStyleSheetLinkingElement.h +++ b/dom/base/nsIStyleSheetLinkingElement.h @@ -101,6 +101,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, diff --git a/dom/base/nsStyleLinkElement.cpp b/dom/base/nsStyleLinkElement.cpp index 7ea7fce40c..0fbdbd5860 100644 --- a/dom/base/nsStyleLinkElement.cpp +++ b/dom/base/nsStyleLinkElement.cpp @@ -40,6 +40,7 @@ nsStyleLinkElement::nsStyleLinkElement() : mDontLoadStyle(false) , mUpdatesEnabled(true) , mLineNumber(1) + , mColumnNumber(1) { } @@ -127,6 +128,18 @@ nsStyleLinkElement::GetLineNumber() return mLineNumber; } +/* virtual */ void +nsStyleLinkElement::SetColumnNumber(uint32_t aColumnNumber) +{ + mColumnNumber = aColumnNumber; +} + +/* virtual */ uint32_t +nsStyleLinkElement::GetColumnNumber() +{ + return mColumnNumber; +} + /* static */ bool nsStyleLinkElement::IsImportEnabled() { @@ -412,8 +425,10 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument, if (!nsStyleUtil::CSPAllowsInlineStyle(thisContent, thisContent->NodePrincipal(), doc->GetDocumentURI(), - mLineNumber, text, &rv)) + mLineNumber, mColumnNumber, text, + &rv)) { return rv; + } // Parse the style sheet. rv = doc->CSSLoader()-> diff --git a/dom/base/nsStyleLinkElement.h b/dom/base/nsStyleLinkElement.h index a0664106aa..79ac6abbaa 100644 --- a/dom/base/nsStyleLinkElement.h +++ b/dom/base/nsStyleLinkElement.h @@ -54,6 +54,8 @@ public: virtual void OverrideBaseURI(nsIURI* aNewBaseURI) override; virtual void SetLineNumber(uint32_t aLineNumber) override; virtual uint32_t GetLineNumber() override; + void SetColumnNumber(uint32_t aColumnNumber) override; + uint32_t GetColumnNumber() override; enum RelValue { ePREFETCH = 0x00000001, @@ -140,6 +142,7 @@ protected: bool mDontLoadStyle; bool mUpdatesEnabled; uint32_t mLineNumber; + uint32_t mColumnNumber; }; #endif /* nsStyleLinkElement_h___ */ diff --git a/dom/base/nsStyledElement.cpp b/dom/base/nsStyledElement.cpp index 42b632e71a..b9331c076d 100644 --- a/dom/base/nsStyledElement.cpp +++ b/dom/base/nsStyledElement.cpp @@ -191,7 +191,7 @@ nsStyledElement::ParseStyleAttribute(const nsAString& aValue, if (!isNativeAnon && !nsStyleUtil::CSPAllowsInlineStyle(nullptr, NodePrincipal(), - doc->GetDocumentURI(), 0, aValue, + doc->GetDocumentURI(), 0, 0, aValue, nullptr)) return; diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp index 7d68394850..b2e5a19854 100644 --- a/dom/events/EventListenerManager.cpp +++ b/dom/events/EventListenerManager.cpp @@ -786,28 +786,22 @@ EventListenerManager::SetEventHandler(nsIAtom* aName, rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp)); NS_ENSURE_SUCCESS(rv, rv); - if (csp) { - // let's generate a script sample and pass it as aContent, - // it will not match the hash, but allows us to pass - // the script sample in aContent. - nsAutoString scriptSample, attr, tagName(NS_LITERAL_STRING("UNKNOWN")); - aName->ToString(attr); - nsCOMPtr domNode(do_QueryInterface(mTarget)); - if (domNode) { - domNode->GetNodeName(tagName); - } - // build a "script sample" based on what we know about this element - scriptSample.Assign(attr); - scriptSample.AppendLiteral(" attribute on "); - scriptSample.Append(tagName); - scriptSample.AppendLiteral(" element"); + unsigned lineNum = 0; + unsigned columnNum = 0; + JSContext* cx = nsContentUtils::GetCurrentJSContext(); + if (cx && !JS::DescribeScriptedCaller(cx, nullptr, &lineNum, &columnNum)) { + JS_ClearPendingException(cx); + } + + if (csp) { bool allowsInlineScript = true; rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT, EmptyString(), // aNonce true, // aParserCreated (true because attribute event handler) - scriptSample, - 0, // aLineNumber + aBody, + lineNum, // aLineNumber + columnNum, // aColumnNumber &allowsInlineScript); NS_ENSURE_SUCCESS(rv, rv); diff --git a/dom/interfaces/security/nsIContentSecurityPolicy.idl b/dom/interfaces/security/nsIContentSecurityPolicy.idl index a8b508ce7e..bdcbf908bf 100644 --- a/dom/interfaces/security/nsIContentSecurityPolicy.idl +++ b/dom/interfaces/security/nsIContentSecurityPolicy.idl @@ -140,6 +140,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). @@ -148,7 +150,8 @@ interface nsIContentSecurityPolicy : nsISerializable in AString aNonce, in boolean aParserCreated, in AString aContent, - in unsigned long aLineNumber); + in unsigned long aLineNumber, + in unsigned long aColumnNumber); /** * whether this policy allows eval and eval-like functions @@ -188,6 +191,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 @@ -202,6 +207,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); diff --git a/dom/jsurl/nsJSProtocolHandler.cpp b/dom/jsurl/nsJSProtocolHandler.cpp index fe3c12b76a..9a9541164f 100644 --- a/dom/jsurl/nsJSProtocolHandler.cpp +++ b/dom/jsurl/nsJSProtocolHandler.cpp @@ -185,6 +185,7 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel, true, // aParserCreated EmptyString(), // aContent 0, // aLineNumber + 0, // aColumnNumber &allowsInlineScript); //return early if inline scripts are not allowed diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp index c07c4b184f..6c211d53f2 100644 --- a/dom/script/ScriptLoader.cpp +++ b/dom/script/ScriptLoader.cpp @@ -1474,6 +1474,7 @@ CSPAllowsInlineScript(nsIScriptElement *aElement, nsIDocument *aDocument) rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT, nonce, parserCreated, scriptText, aElement->GetScriptLineNumber(), + aElement->GetScriptColumnNumber(), &allowInlineScript); return allowInlineScript; } @@ -2695,10 +2696,11 @@ ScriptLoader::VerifySRI(ScriptLoadRequest* aRequest, nsAutoCString violationURISpec; mDocument->GetDocumentURI()->GetAsciiSpec(violationURISpec); uint32_t lineNo = aRequest->Element() ? aRequest->Element()->GetScriptLineNumber() : 0; + uint32_t columnNo = aRequest->Element() ? aRequest->Element()->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; } } diff --git a/dom/script/nsIScriptElement.h b/dom/script/nsIScriptElement.h index ba3c7dd453..a654291aa0 100644 --- a/dom/script/nsIScriptElement.h +++ b/dom/script/nsIScriptElement.h @@ -30,6 +30,7 @@ public: explicit nsIScriptElement(mozilla::dom::FromParser aFromParser) : mLineNumber(1), + mColumnNumber(1), mAlreadyStarted(false), mMalformed(false), mDoneAddingChildren(aFromParser == mozilla::dom::NOT_FROM_PARSER || @@ -138,6 +139,16 @@ public: return mLineNumber; } + void SetScriptColumnNumber(uint32_t aColumnNumber) + { + mColumnNumber = aColumnNumber; + } + + uint32_t GetScriptColumnNumber() + { + return mColumnNumber; + } + void SetIsMalformed() { mMalformed = true; @@ -281,6 +292,11 @@ protected: */ uint32_t mLineNumber; + /** + * The start column number of the script. + */ + uint32_t mColumnNumber; + /** * The "already started" flag per HTML5. */ diff --git a/dom/security/CSPEvalChecker.cpp b/dom/security/CSPEvalChecker.cpp index 42b5610c7d..51e26a6808 100644 --- a/dom/security/CSPEvalChecker.cpp +++ b/dom/security/CSPEvalChecker.cpp @@ -46,7 +46,7 @@ CheckInternal(nsIContentSecurityPolicy* aCSP, if (reportViolation) { aCSP->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL, aFileNameString, aExpression, aLineNum, - EmptyString(), EmptyString()); + aColumnNum, EmptyString(), EmptyString()); } return NS_OK; diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp index 5c52d0f201..a52e741e8d 100644 --- a/dom/security/nsCSPContext.cpp +++ b/dom/security/nsCSPContext.cpp @@ -40,6 +40,7 @@ #include "nsScriptSecurityManager.h" #include "nsStringStream.h" #include "mozilla/Logging.h" +#include "mozilla/Preferences.h" #include "mozilla/dom/CSPReportBinding.h" #include "mozilla/dom/CSPDictionariesBinding.h" #include "mozilla/net/ReferrerPolicy.h" @@ -271,7 +272,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 */ } } } @@ -298,6 +300,14 @@ nsCSPContext::nsCSPContext() , mLoadingPrincipal(nullptr) , mQueueUpMessages(true) { + static bool sInitialized = false; + if (!sInitialized) { + Preferences::AddIntVarCache(&sScriptSampleMaxLength, + "security.csp.reporting.script-sample.max-length", + 40); + sInitialized = true; + } + CSPCONTEXTLOG(("nsCSPContext::nsCSPContext")); } @@ -470,7 +480,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 @@ -500,9 +511,9 @@ nsCSPContext::reportInlineViolation(nsContentPolicyType aContentType, } nsAutoString codeSample(aContent); - // cap the length of the script sample at 40 chars - if (codeSample.Length() > 40) { - codeSample.Truncate(40); + // cap the length of the script sample + if (codeSample.Length() > ScriptSampleMaxLength()) { + codeSample.Truncate(ScriptSampleMaxLength()); codeSample.AppendLiteral("..."); } AsyncReportViolation(selfISupports, // aBlockedContentSource @@ -512,7 +523,8 @@ nsCSPContext::reportInlineViolation(nsContentPolicyType aContentType, observerSubject, // aObserverSubject NS_ConvertUTF8toUTF16(sourceFile), // aSourceFile codeSample, // aScriptSample - aLineNumber); // aLineNum + aLineNumber, // aLineNum + aColumnNumber); // aColumnNum } NS_IMETHODIMP @@ -521,6 +533,7 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType, bool aParserCreated, const nsAString& aContent, uint32_t aLineNumber, + uint32_t aColumnNumber, bool* outAllowsInline) { *outAllowsInline = true; @@ -565,7 +578,8 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType, aContent, violatedDirective, i, - aLineNumber); + aLineNumber, + aColumnNumber); } } return NS_OK; @@ -584,7 +598,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 @@ -611,8 +626,8 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType, nsIContentPolicy::TYPE_ ## contentPolicyType, \ violatedDirective); \ this->AsyncReportViolation(selfISupports, nullptr, violatedDirective, p, \ - NS_LITERAL_STRING(observerTopic), \ - aSourceFile, aScriptSample, aLineNum); \ + NS_LITERAL_STRING(observerTopic), aSourceFile,\ + aScriptSample, aLineNum, aColumnNum); \ } \ PR_END_MACRO; \ break @@ -644,6 +659,7 @@ nsCSPContext::LogViolationDetails(uint16_t aViolationType, const nsAString& aSourceFile, const nsAString& aScriptSample, int32_t aLineNum, + int32_t aColumnNum, const nsAString& aNonce, const nsAString& aContent) { @@ -844,6 +860,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); @@ -907,8 +924,19 @@ nsCSPContext::GatherSecurityPolicyViolationEventData( aViolationEventInit.mSourceFile = aSourceFile; } - // sample + // sample, max 40 chars. aViolationEventInit.mSample = aScriptSample; + uint32_t length = aViolationEventInit.mSample.Length(); + if (length > ScriptSampleMaxLength()) { + uint32_t desiredLength = ScriptSampleMaxLength(); + // Don't cut off right before a low surrogate. Just include it. + if (NS_IS_LOW_SURROGATE(aViolationEventInit.mSample[desiredLength])) { + desiredLength++; + } + aViolationEventInit.mSample.Replace(ScriptSampleMaxLength(), + length - desiredLength, + nsContentUtils::GetLocalizedEllipsis()); + } // disposition aViolationEventInit.mDisposition = mPolicies[aViolatedPolicyIndex]->getReportOnlyFlag() @@ -936,8 +964,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; @@ -1012,7 +1039,8 @@ nsCSPContext::SendReports( reportURICstring.get())); logToConsole(u"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 } @@ -1054,7 +1082,8 @@ nsCSPContext::SendReports( const char16_t* params[] = { reportURIs[r].get() }; logToConsole(u"reportURInotHttpsOrHttp2", params, ArrayLength(params), aViolationEventInit.mSourceFile, aViolationEventInit.mSample, - aViolationEventInit.mLineNumber, 0, nsIScriptError::errorFlag); + aViolationEventInit.mLineNumber, aViolationEventInit.mColumnNumber, + nsIScriptError::errorFlag); continue; } @@ -1119,7 +1148,8 @@ nsCSPContext::SendReports( CSPCONTEXTLOG(("AsyncOpen failed for report URI %s", params[0])); logToConsole(u"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())); } @@ -1162,6 +1192,7 @@ class CSPReportSenderRunnable final : public Runnable const nsAString& aSourceFile, const nsAString& aScriptSample, uint32_t aLineNum, + uint32_t aColumnNum, nsCSPContext* aCSPContext) : mBlockedContentSource(aBlockedContentSource) , mOriginalURI(aOriginalURI) @@ -1171,6 +1202,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"); @@ -1208,7 +1240,7 @@ class CSPReportSenderRunnable final : public Runnable blockedURI, blockedDataStr, mOriginalURI, mViolatedDirective, mViolatedPolicyIndex, mSourceFile, mScriptSample, mLineNum, - init); + mColumnNum, init); NS_ENSURE_SUCCESS(rv, rv); // 1) notify observers @@ -1223,15 +1255,22 @@ class CSPReportSenderRunnable final : public Runnable mCSPContext->SendReports(init, mViolatedPolicyIndex); // 3) log to console (one per policy violation) + // if mBlockedContentSource is not a URI, it could be a string + nsCOMPtr blockedString = do_QueryInterface(mBlockedContentSource); if (blockedURI) { blockedURI->GetSpec(blockedDataStr); - bool isData = false; - rv = blockedURI->SchemeIs("data", &isData); - if (NS_SUCCEEDED(rv) && isData) { - blockedDataStr.Truncate(40); - blockedDataStr.AppendASCII("..."); + if (blockedDataStr.Length() > nsCSPContext::ScriptSampleMaxLength()) { + bool isData = false; + rv = blockedURI->SchemeIs("data", &isData); + if (NS_SUCCEEDED(rv) && isData && + blockedDataStr.Length() > nsCSPContext::ScriptSampleMaxLength()) { + blockedDataStr.Truncate(nsCSPContext::ScriptSampleMaxLength()); + blockedDataStr.Append(NS_ConvertUTF16toUTF8(nsContentUtils::GetLocalizedEllipsis())); + } } + } else if (blockedString) { + blockedString->GetData(blockedDataStr); } if (blockedDataStr.Length() > 0) { @@ -1241,7 +1280,7 @@ class CSPReportSenderRunnable final : public Runnable mCSPContext->logToConsole(mReportOnlyFlag ? u"CSPROViolationWithURI" : u"CSPViolationWithURI", params, ArrayLength(params), mSourceFile, mScriptSample, - mLineNum, 0, nsIScriptError::errorFlag); + mLineNum, mColumnNum, nsIScriptError::errorFlag); } // 4) fire violation event @@ -1260,6 +1299,7 @@ class CSPReportSenderRunnable final : public Runnable nsString mSourceFile; nsString mScriptSample; uint32_t mLineNum; + uint32_t mColumnNum; RefPtr mCSPContext; }; @@ -1287,6 +1327,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, @@ -1296,7 +1338,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); @@ -1309,6 +1352,7 @@ nsCSPContext::AsyncReportViolation(nsISupports* aBlockedContentSource, aSourceFile, aScriptSample, aLineNum, + aColumnNum, this)); return NS_OK; } diff --git a/dom/security/nsCSPContext.h b/dom/security/nsCSPContext.h index 1d3122af80..272e4c733a 100644 --- a/dom/security/nsCSPContext.h +++ b/dom/security/nsCSPContext.h @@ -85,6 +85,7 @@ class nsCSPContext : public nsIContentSecurityPolicy nsAString& aSourceFile, nsAString& aScriptSample, uint32_t aLineNum, + uint32_t aColumnNum, mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit); nsresult SendReports( @@ -101,7 +102,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 @@ -110,10 +112,14 @@ class nsCSPContext : public nsIContentSecurityPolicy mLoadingPrincipal = nullptr; } - nsWeakPtr GetLoadingContext(){ + nsWeakPtr GetLoadingContext() { return mLoadingContext; } + static uint32_t ScriptSampleMaxLength() { + return std::max(sScriptSampleMaxLength, 0); + } + private: bool permitsInternal(CSPDirective aDir, nsIURI* aContentLocation, @@ -132,7 +138,10 @@ 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; nsString mReferrer; uint64_t mInnerWindowID; // used for web console logging diff --git a/dom/smil/nsSMILCSSValueType.cpp b/dom/smil/nsSMILCSSValueType.cpp index 71ef27cd63..93e05aca07 100644 --- a/dom/smil/nsSMILCSSValueType.cpp +++ b/dom/smil/nsSMILCSSValueType.cpp @@ -405,7 +405,7 @@ nsSMILCSSValueType::ValueFromString(nsCSSPropertyID aPropID, if (doc && !nsStyleUtil::CSPAllowsInlineStyle(nullptr, doc->NodePrincipal(), doc->GetDocumentURI(), - 0, aString, nullptr)) { + 0, 0, aString, nullptr)) { return; } diff --git a/dom/webidl/CSPReport.webidl b/dom/webidl/CSPReport.webidl index 390898c83d..301ca2885c 100644 --- a/dom/webidl/CSPReport.webidl +++ b/dom/webidl/CSPReport.webidl @@ -16,6 +16,7 @@ dictionary CSPReportProperties { DOMString source-file; DOMString script-sample; long line-number; + long column-number; }; dictionary CSPReport { diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index 199f6ea56a..0309a67375 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -547,14 +547,21 @@ class LogViolationDetailsRunnable final : public WorkerMainThreadRunnable { nsString mFileName; uint32_t mLineNum; + uint32_t mColumnNum; + nsString mScriptSample; public: LogViolationDetailsRunnable(WorkerPrivate* aWorker, const nsString& aFileName, - uint32_t aLineNum) + uint32_t aLineNum, + uint32_t aColumnNum, + const nsAString& aScriptSample) : WorkerMainThreadRunnable(aWorker, NS_LITERAL_CSTRING("RuntimeService :: LogViolationDetails")) - , mFileName(aFileName), mLineNum(aLineNum) + , mFileName(aFileName) + , mLineNum(aLineNum) + , mColumnNum(aColumnNum) + , mScriptSample(aScriptSample) { MOZ_ASSERT(aWorker); } @@ -566,24 +573,38 @@ private: }; bool -ContentSecurityPolicyAllows(JSContext* aCx) +ContentSecurityPolicyAllows(JSContext* aCx, JS::HandleValue aValue) { WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx); worker->AssertIsOnWorkerThread(); if (worker->GetReportCSPViolations()) { + JS::Rooted jsString(aCx, JS::ToString(aCx, aValue)); + if (NS_WARN_IF(!jsString)) { + JS_ClearPendingException(aCx); + return false; + } + + nsAutoJSString scriptSample; + if (NS_WARN_IF(!scriptSample.init(aCx, jsString))) { + JS_ClearPendingException(aCx); + return false; + } + 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 runnable = - new LogViolationDetailsRunnable(worker, fileName, lineNum); + new LogViolationDetailsRunnable(worker, fileName, lineNum, columnNum, + scriptSample); ErrorResult rv; runnable->Dispatch(Killing, rv); @@ -2698,11 +2719,9 @@ LogViolationDetailsRunnable::MainThreadRun() nsIContentSecurityPolicy* csp = mWorkerPrivate->GetCSP(); if (csp) { - NS_NAMED_LITERAL_STRING(scriptSample, - "Call to eval() or related function blocked by CSP."); if (mWorkerPrivate->GetReportCSPViolations()) { csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL, - mFileName, scriptSample, mLineNum, + mFileName, mScriptSample, mLineNum, mColumnNum, EmptyString(), EmptyString()); } } diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp index 646182bfd3..561759cc4c 100644 --- a/dom/workers/ScriptLoader.cpp +++ b/dom/workers/ScriptLoader.cpp @@ -1167,7 +1167,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; } diff --git a/dom/xbl/nsXBLContentSink.cpp b/dom/xbl/nsXBLContentSink.cpp index 0f54d62b49..3232f2a0fb 100644 --- a/dom/xbl/nsXBLContentSink.cpp +++ b/dom/xbl/nsXBLContentSink.cpp @@ -248,10 +248,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 } diff --git a/dom/xbl/nsXBLContentSink.h b/dom/xbl/nsXBLContentSink.h index 93c1454a40..a09ee78b07 100644 --- a/dom/xbl/nsXBLContentSink.h +++ b/dom/xbl/nsXBLContentSink.h @@ -69,7 +69,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; @@ -89,7 +90,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; diff --git a/dom/xml/nsXMLContentSink.cpp b/dom/xml/nsXMLContentSink.cpp index 1e6f35eb89..7db1ea4a6a 100644 --- a/dom/xml/nsXMLContentSink.cpp +++ b/dom/xml/nsXMLContentSink.cpp @@ -446,7 +446,8 @@ nsXMLContentSink::SetParser(nsParserBase* aParser) 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) { @@ -466,6 +467,7 @@ nsXMLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount, ) { nsCOMPtr sele = do_QueryInterface(content); sele->SetScriptLineNumber(aLineNumber); + sele->SetScriptColumnNumber(aColumnNumber); sele->SetCreatorParser(GetParser()); } @@ -500,6 +502,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); } } } @@ -918,10 +921,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 @@ -929,6 +933,7 @@ nsXMLContentSink::HandleStartElement(const char16_t *aName, const char16_t **aAtts, uint32_t aAttsCount, uint32_t aLineNumber, + uint32_t aColumnNumber, bool aInterruptable) { NS_PRECONDITION(aAttsCount % 2 == 0, "incorrect aAttsCount"); @@ -963,7 +968,7 @@ nsXMLContentSink::HandleStartElement(const char16_t *aName, nsIDOMNode::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); diff --git a/dom/xml/nsXMLContentSink.h b/dom/xml/nsXMLContentSink.h index f08f99a3a0..ea190954a2 100644 --- a/dom/xml/nsXMLContentSink.h +++ b/dom/xml/nsXMLContentSink.h @@ -114,7 +114,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); @@ -161,7 +162,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); diff --git a/dom/xml/nsXMLFragmentContentSink.cpp b/dom/xml/nsXMLFragmentContentSink.cpp index 04d688c81e..a4bb406351 100644 --- a/dom/xml/nsXMLFragmentContentSink.cpp +++ b/dom/xml/nsXMLFragmentContentSink.cpp @@ -83,7 +83,8 @@ protected: nsIAtom* 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; @@ -199,7 +200,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*/) { @@ -207,6 +209,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); diff --git a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp index c9bcc31ff0..6137e87c11 100644 --- a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp +++ b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp @@ -122,7 +122,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) { NS_PRECONDITION(aAttsCount % 2 == 0, "incorrect aAttsCount"); diff --git a/dom/xul/nsXULContentSink.cpp b/dom/xul/nsXULContentSink.cpp index c631e0424d..28e269d59f 100644 --- a/dom/xul/nsXULContentSink.cpp +++ b/dom/xul/nsXULContentSink.cpp @@ -437,7 +437,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 @@ -694,7 +695,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)); @@ -704,7 +705,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)); diff --git a/js/public/Principals.h b/js/public/Principals.h index 4f2670b653..ec7083d768 100644 --- a/js/public/Principals.h +++ b/js/public/Principals.h @@ -64,10 +64,10 @@ typedef bool /* * Used to check if a CSP instance wants to disable eval() and friends. - * See js_CheckCSPPermitsJSAction() in jsobj. + * See GlobalObject::isRuntimeCodeGenEnabled() in vm/GlobalObject.cpp. */ typedef bool -(* JSCSPEvalChecker)(JSContext* cx); +(* JSCSPEvalChecker)(JSContext* cx, JS::HandleValue aValue); struct JSSecurityCallbacks { JSCSPEvalChecker contentSecurityPolicyAllows; diff --git a/js/src/builtin/Eval.cpp b/js/src/builtin/Eval.cpp index 53fa789313..b60330b516 100644 --- a/js/src/builtin/Eval.cpp +++ b/js/src/builtin/Eval.cpp @@ -227,7 +227,7 @@ EvalKernel(JSContext* cx, HandleValue v, EvalType evalType, AbstractFramePtr cal AssertInnerizedEnvironmentChain(cx, *env); Rooted envGlobal(cx, &env->global()); - if (!GlobalObject::isRuntimeCodeGenEnabled(cx, envGlobal)) { + if (!GlobalObject::isRuntimeCodeGenEnabled(cx, v, envGlobal)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_EVAL); return false; } @@ -330,7 +330,8 @@ js::DirectEvalStringFromIon(JSContext* cx, AssertInnerizedEnvironmentChain(cx, *env); Rooted envGlobal(cx, &env->global()); - if (!GlobalObject::isRuntimeCodeGenEnabled(cx, envGlobal)) { + RootedValue v(cx, StringValue(str)); + if (!GlobalObject::isRuntimeCodeGenEnabled(cx, v, envGlobal)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_EVAL); return false; } diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index ec13ce3e9a..ad2e1fcd95 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -1625,13 +1625,6 @@ static bool FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generatorKind, FunctionAsyncKind asyncKind) { - // Block this call if security callbacks forbid it. - Rooted global(cx, &args.callee().global()); - if (!GlobalObject::isRuntimeCodeGenEnabled(cx, global)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_FUNCTION); - return false; - } - bool isStarGenerator = generatorKind == StarGenerator; bool isAsync = asyncKind == AsyncFunction; MOZ_ASSERT(generatorKind != LegacyGenerator); @@ -1733,6 +1726,14 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator if (!functionText) return false; + // Block this call if security callbacks forbid it. + Rooted global(cx, &args.callee().global()); + RootedValue v(cx, StringValue(functionText)); + if (!GlobalObject::isRuntimeCodeGenEnabled(cx, v, global)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_FUNCTION); + return false; + } + /* * NB: (new Function) is not lexically closed by its caller, it's just an * anonymous function in the top-level scope that its constructor inhabits. diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index 1321be9e9b..8d73fa15cc 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -543,17 +543,23 @@ GlobalObject::initSelfHostingBuiltins(JSContext* cx, Handle globa } /* static */ bool -GlobalObject::isRuntimeCodeGenEnabled(JSContext* cx, Handle global) +GlobalObject::isRuntimeCodeGenEnabled(JSContext* cx, HandleValue code, + Handle global) { HeapSlot& v = global->getSlotRef(RUNTIME_CODEGEN_ENABLED); if (v.isUndefined()) { /* * If there are callbacks, make sure that the CSP callback is installed - * and that it permits runtime code generation, then cache the result. + * and that it permits runtime code generation. */ JSCSPEvalChecker allows = cx->runtime()->securityCallbacks->contentSecurityPolicyAllows; - Value boolValue = BooleanValue(!allows || allows(cx)); - v.set(global, HeapSlot::Slot, RUNTIME_CODEGEN_ENABLED, boolValue); + if (allows) + return allows(cx, code); + + // Let's cache the result only if the contentSecurityPolicyAllows callback is not set. In + // this way, contentSecurityPolicyAllows callback is executed each time, with the current + // HandleValue code. + v.set(global, HeapSlot::Slot, RUNTIME_CODEGEN_ENABLED, JS::TrueValue()); } return !v.isFalse(); } diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index 355d055fb6..9aa47638d0 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -803,7 +803,8 @@ class GlobalObject : public NativeObject template inline Value createArrayFromBuffer() const; - static bool isRuntimeCodeGenEnabled(JSContext* cx, Handle global); + static bool isRuntimeCodeGenEnabled(JSContext* cx, HandleValue code, + Handle global); // Warn about use of the deprecated watch/unwatch functions in the global // in which |obj| was created, if no prior warning was given. diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp index 48ca1739dc..ff4ff80eba 100644 --- a/layout/style/Loader.cpp +++ b/layout/style/Loader.cpp @@ -955,7 +955,7 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader, csp->LogViolationDetails( nsIContentSecurityPolicy::VIOLATION_TYPE_REQUIRE_SRI_FOR_STYLE, NS_ConvertUTF8toUTF16(spec), EmptyString(), - 0, EmptyString(), EmptyString()); + 0, 0, EmptyString(), EmptyString()); return NS_OK; } } else { diff --git a/layout/style/nsStyleUtil.cpp b/layout/style/nsStyleUtil.cpp index 9c3c0f449a..274f5140f2 100644 --- a/layout/style/nsStyleUtil.cpp +++ b/layout/style/nsStyleUtil.cpp @@ -739,6 +739,7 @@ nsStyleUtil::CSPAllowsInlineStyle(nsIContent* aContent, nsIPrincipal* aPrincipal, nsIURI* aSourceURI, uint32_t aLineNumber, + uint32_t aColumnNumber, const nsSubstring& aStyleText, nsresult* aRv) { @@ -776,7 +777,7 @@ nsStyleUtil::CSPAllowsInlineStyle(nsIContent* aContent, rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_STYLESHEET, nonce, false, // aParserCreated only applies to scripts - aStyleText, aLineNumber, + aStyleText, aLineNumber, aColumnNumber, &allowInlineStyle); NS_ENSURE_SUCCESS(rv, false); diff --git a/layout/style/nsStyleUtil.h b/layout/style/nsStyleUtil.h index e5b7a055ff..95cc2c5ac6 100644 --- a/layout/style/nsStyleUtil.h +++ b/layout/style/nsStyleUtil.h @@ -164,6 +164,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 @@ -175,6 +178,7 @@ public: nsIPrincipal* aPrincipal, nsIURI* aSourceURI, uint32_t aLineNumber, + uint32_t aColumnNumber, const nsSubstring& aStyleText, nsresult* aRv); diff --git a/parser/htmlparser/nsExpatDriver.cpp b/parser/htmlparser/nsExpatDriver.cpp index e35a1da256..743a6547d2 100644 --- a/parser/htmlparser/nsExpatDriver.cpp +++ b/parser/htmlparser/nsExpatDriver.cpp @@ -394,7 +394,8 @@ nsExpatDriver::HandleStartElement(const char16_t *aValue, nsresult rv = mSink-> HandleStartElement(aValue, aAtts, attrArrayLength, - XML_GetCurrentLineNumber(mExpatParser)); + XML_GetCurrentLineNumber(mExpatParser), + XML_GetCurrentColumnNumber(mExpatParser)); MaybeStopParser(rv); } } diff --git a/parser/htmlparser/nsIExpatSink.idl b/parser/htmlparser/nsIExpatSink.idl index df0b2d869f..d8217b60c8 100644 --- a/parser/htmlparser/nsIExpatSink.idl +++ b/parser/htmlparser/nsIExpatSink.idl @@ -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. diff --git a/parser/xml/nsSAXXMLReader.cpp b/parser/xml/nsSAXXMLReader.cpp index a84e0d63ba..2d0d23569d 100644 --- a/parser/xml/nsSAXXMLReader.cpp +++ b/parser/xml/nsSAXXMLReader.cpp @@ -82,7 +82,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; diff --git a/rdf/base/nsRDFContentSink.cpp b/rdf/base/nsRDFContentSink.cpp index ae05a9381b..ec9eb2fc8d 100644 --- a/rdf/base/nsRDFContentSink.cpp +++ b/rdf/base/nsRDFContentSink.cpp @@ -388,8 +388,9 @@ RDFContentSinkImpl::QueryInterface(REFNSIID iid, void** result) NS_IMETHODIMP RDFContentSinkImpl::HandleStartElement(const char16_t *aName, const char16_t **aAtts, - uint32_t aAttsCount, - uint32_t aLineNumber) + uint32_t aAttsCount, + uint32_t aLineNumber, + uint32_t aColumnNumber) { FlushText();