зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1406794 - Provide the CSP keywords in both UTF8 and UTF16 forms. r=ckerschb
This avoids the need for numerous 8-to-16-bit and 16-to-8-bit string conversions. The patch also introduces a higher-order macro, FOR_EACH_CSP_KEYWORD, which defines all the stuff about the keywords in a single place and makes the code nicer. --HG-- extra : rebase_source : b0f655546aa397749bb18dc7d6d27fbc12fe8fca
This commit is contained in:
Родитель
0b432c20bc
Коммит
159f6b5627
|
@ -552,7 +552,7 @@ nsCSPParser::keywordSource()
|
|||
return nullptr;
|
||||
}
|
||||
mStrictDynamic = true;
|
||||
return new nsCSPKeywordSrc(CSP_KeywordToEnum(mCurToken));
|
||||
return new nsCSPKeywordSrc(CSP_UTF16KeywordToEnum(mCurToken));
|
||||
}
|
||||
|
||||
if (CSP_IsKeyword(mCurToken, CSP_UNSAFE_INLINE)) {
|
||||
|
@ -571,7 +571,8 @@ nsCSPParser::keywordSource()
|
|||
}
|
||||
// cache if we encounter 'unsafe-inline' so we can invalidate (ignore) it in
|
||||
// case that script-src directive also contains hash- or nonce-.
|
||||
mUnsafeInlineKeywordSrc = new nsCSPKeywordSrc(CSP_KeywordToEnum(mCurToken));
|
||||
mUnsafeInlineKeywordSrc =
|
||||
new nsCSPKeywordSrc(CSP_UTF16KeywordToEnum(mCurToken));
|
||||
return mUnsafeInlineKeywordSrc;
|
||||
}
|
||||
|
||||
|
@ -581,7 +582,7 @@ nsCSPParser::keywordSource()
|
|||
if (doc) {
|
||||
doc->SetHasUnsafeEvalCSP(true);
|
||||
}
|
||||
return new nsCSPKeywordSrc(CSP_KeywordToEnum(mCurToken));
|
||||
return new nsCSPKeywordSrc(CSP_UTF16KeywordToEnum(mCurToken));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -665,7 +666,8 @@ nsCSPParser::nonceSource()
|
|||
NS_ConvertUTF16toUTF8(mCurValue).get()));
|
||||
|
||||
// Check if mCurToken begins with "'nonce-" and ends with "'"
|
||||
if (!StringBeginsWith(mCurToken, NS_ConvertUTF8toUTF16(CSP_EnumToKeyword(CSP_NONCE)),
|
||||
if (!StringBeginsWith(mCurToken,
|
||||
nsDependentString(CSP_EnumToUTF16Keyword(CSP_NONCE)),
|
||||
nsASCIICaseInsensitiveStringComparator()) ||
|
||||
mCurToken.Last() != SINGLEQUOTE) {
|
||||
return nullptr;
|
||||
|
@ -861,8 +863,7 @@ nsCSPParser::sourceList(nsTArray<nsCSPBaseSrc*>& outSrcs)
|
|||
}
|
||||
// Otherwise, we ignore 'none' and report a warning
|
||||
else {
|
||||
NS_ConvertUTF8toUTF16 unicodeNone(CSP_EnumToKeyword(CSP_NONE));
|
||||
const char16_t* params[] = { unicodeNone.get() };
|
||||
const char16_t* params[] = { CSP_EnumToUTF16Keyword(CSP_NONE) };
|
||||
logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringUnknownOption",
|
||||
params, ArrayLength(params));
|
||||
}
|
||||
|
@ -1252,10 +1253,10 @@ nsCSPParser::directive()
|
|||
// Even though we invalidate all of the srcs internally, we don't want to log
|
||||
// messages for the srcs: (1) strict-dynamic, (2) unsafe-inline,
|
||||
// (3) nonces, and (4) hashes
|
||||
if (!srcStr.EqualsASCII(CSP_EnumToKeyword(CSP_STRICT_DYNAMIC)) &&
|
||||
!srcStr.EqualsASCII(CSP_EnumToKeyword(CSP_UNSAFE_EVAL)) &&
|
||||
!StringBeginsWith(NS_ConvertUTF16toUTF8(srcStr), NS_LITERAL_CSTRING("'nonce-")) &&
|
||||
!StringBeginsWith(NS_ConvertUTF16toUTF8(srcStr), NS_LITERAL_CSTRING("'sha")))
|
||||
if (!srcStr.EqualsASCII(CSP_EnumToUTF8Keyword(CSP_STRICT_DYNAMIC)) &&
|
||||
!srcStr.EqualsASCII(CSP_EnumToUTF8Keyword(CSP_UNSAFE_EVAL)) &&
|
||||
!StringBeginsWith(srcStr, nsDependentString(CSP_EnumToUTF16Keyword(CSP_NONCE))) &&
|
||||
!StringBeginsWith(srcStr, NS_LITERAL_STRING("'sha")))
|
||||
{
|
||||
const char16_t* params[] = { srcStr.get() };
|
||||
logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringSrcForStrictDynamic",
|
||||
|
|
|
@ -322,7 +322,7 @@ CSP_IsDirective(const nsAString& aValue, CSPDirective aDir)
|
|||
bool
|
||||
CSP_IsKeyword(const nsAString& aValue, enum CSPKeyword aKey)
|
||||
{
|
||||
return aValue.LowerCaseEqualsASCII(CSP_EnumToKeyword(aKey));
|
||||
return aValue.LowerCaseEqualsASCII(CSP_EnumToUTF8Keyword(aKey));
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -331,14 +331,10 @@ CSP_IsQuotelessKeyword(const nsAString& aKey)
|
|||
nsString lowerKey = PromiseFlatString(aKey);
|
||||
ToLowerCase(lowerKey);
|
||||
|
||||
static_assert(CSP_LAST_KEYWORD_VALUE ==
|
||||
(sizeof(CSPStrKeywords) / sizeof(CSPStrKeywords[0])),
|
||||
"CSP_LAST_KEYWORD_VALUE does not match length of CSPStrKeywords");
|
||||
|
||||
nsAutoString keyword;
|
||||
for (uint32_t i = 0; i < CSP_LAST_KEYWORD_VALUE; i++) {
|
||||
// skipping the leading ' and trimming the trailing '
|
||||
keyword.AssignASCII(CSPStrKeywords[i] + 1);
|
||||
keyword.AssignASCII(gCSPUTF8Keywords[i] + 1);
|
||||
keyword.Trim("'", false, true);
|
||||
if (lowerKey.Equals(keyword)) {
|
||||
return true;
|
||||
|
@ -482,7 +478,7 @@ nsCSPBaseSrc::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
|
|||
bool aParserCreated) const
|
||||
{
|
||||
CSPUTILSLOG(("nsCSPBaseSrc::allows, aKeyWord: %s, a HashOrNonce: %s",
|
||||
aKeyword == CSP_HASH ? "hash" : CSP_EnumToKeyword(aKeyword),
|
||||
aKeyword == CSP_HASH ? "hash" : CSP_EnumToUTF8Keyword(aKeyword),
|
||||
NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
|
||||
return false;
|
||||
}
|
||||
|
@ -827,7 +823,7 @@ nsCSPKeywordSrc::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
|
|||
bool aParserCreated) const
|
||||
{
|
||||
CSPUTILSLOG(("nsCSPKeywordSrc::allows, aKeyWord: %s, aHashOrNonce: %s, mInvalidated: %s",
|
||||
CSP_EnumToKeyword(aKeyword),
|
||||
CSP_EnumToUTF8Keyword(aKeyword),
|
||||
NS_ConvertUTF16toUTF8(aHashOrNonce).get(),
|
||||
mInvalidated ? "yes" : "false"));
|
||||
|
||||
|
@ -853,7 +849,7 @@ nsCSPKeywordSrc::visit(nsCSPSrcVisitor* aVisitor) const
|
|||
void
|
||||
nsCSPKeywordSrc::toString(nsAString& outStr) const
|
||||
{
|
||||
outStr.AppendASCII(CSP_EnumToKeyword(mKeyword));
|
||||
outStr.Append(CSP_EnumToUTF16Keyword(mKeyword));
|
||||
}
|
||||
|
||||
/* ===== nsCSPNonceSrc ==================== */
|
||||
|
@ -886,7 +882,8 @@ nsCSPNonceSrc::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
|
|||
bool aParserCreated) const
|
||||
{
|
||||
CSPUTILSLOG(("nsCSPNonceSrc::allows, aKeyWord: %s, a HashOrNonce: %s",
|
||||
CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
|
||||
CSP_EnumToUTF8Keyword(aKeyword),
|
||||
NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
|
||||
|
||||
if (aKeyword != CSP_NONCE) {
|
||||
return false;
|
||||
|
@ -904,7 +901,7 @@ nsCSPNonceSrc::visit(nsCSPSrcVisitor* aVisitor) const
|
|||
void
|
||||
nsCSPNonceSrc::toString(nsAString& outStr) const
|
||||
{
|
||||
outStr.AppendASCII(CSP_EnumToKeyword(CSP_NONCE));
|
||||
outStr.Append(CSP_EnumToUTF16Keyword(CSP_NONCE));
|
||||
outStr.Append(mNonce);
|
||||
outStr.AppendASCII("'");
|
||||
}
|
||||
|
@ -928,7 +925,8 @@ nsCSPHashSrc::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
|
|||
bool aParserCreated) const
|
||||
{
|
||||
CSPUTILSLOG(("nsCSPHashSrc::allows, aKeyWord: %s, a HashOrNonce: %s",
|
||||
CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
|
||||
CSP_EnumToUTF8Keyword(aKeyword),
|
||||
NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
|
||||
|
||||
if (aKeyword != CSP_HASH) {
|
||||
return false;
|
||||
|
@ -1061,7 +1059,8 @@ nsCSPDirective::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
|
|||
bool aParserCreated) const
|
||||
{
|
||||
CSPUTILSLOG(("nsCSPDirective::allows, aKeyWord: %s, a HashOrNonce: %s",
|
||||
CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
|
||||
CSP_EnumToUTF8Keyword(aKeyword),
|
||||
NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
|
||||
|
||||
for (uint32_t i = 0; i < mSrcs.Length(); i++) {
|
||||
if (mSrcs[i]->allows(aKeyword, aHashOrNonce, aParserCreated)) {
|
||||
|
@ -1450,7 +1449,8 @@ nsCSPPolicy::allows(nsContentPolicyType aContentType,
|
|||
bool aParserCreated) const
|
||||
{
|
||||
CSPUTILSLOG(("nsCSPPolicy::allows, aKeyWord: %s, a HashOrNonce: %s",
|
||||
CSP_EnumToKeyword(aKeyword), NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
|
||||
CSP_EnumToUTF8Keyword(aKeyword),
|
||||
NS_ConvertUTF16toUTF8(aHashOrNonce).get()));
|
||||
|
||||
nsCSPDirective* defaultDir = nullptr;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "nsIContentPolicy.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsLiteralString.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
@ -116,61 +117,81 @@ inline CSPDirective CSP_StringToCSPDirective(const nsAString& aDir)
|
|||
return nsIContentSecurityPolicy::NO_DIRECTIVE;
|
||||
}
|
||||
|
||||
// Please add any new enum items not only to CSPKeyword, but also add
|
||||
// a string version for every enum >> using the same index << to
|
||||
// CSPStrKeywords underneath.
|
||||
#define FOR_EACH_CSP_KEYWORD(macro) \
|
||||
macro(CSP_SELF, "'self'") \
|
||||
macro(CSP_UNSAFE_INLINE, "'unsafe-inline'") \
|
||||
macro(CSP_UNSAFE_EVAL, "'unsafe-eval'") \
|
||||
macro(CSP_NONE, "'none'") \
|
||||
macro(CSP_NONCE, "'nonce-") \
|
||||
macro(CSP_REQUIRE_SRI_FOR, "require-sri-for") \
|
||||
macro(CSP_STRICT_DYNAMIC, "'strict-dynamic'")
|
||||
|
||||
enum CSPKeyword {
|
||||
CSP_SELF = 0,
|
||||
CSP_UNSAFE_INLINE,
|
||||
CSP_UNSAFE_EVAL,
|
||||
CSP_NONE,
|
||||
CSP_NONCE,
|
||||
CSP_REQUIRE_SRI_FOR,
|
||||
CSP_STRICT_DYNAMIC,
|
||||
#define KEYWORD_ENUM(id_, string_) id_,
|
||||
FOR_EACH_CSP_KEYWORD(KEYWORD_ENUM)
|
||||
#undef KEYWORD_ENUM
|
||||
|
||||
// CSP_LAST_KEYWORD_VALUE always needs to be the last element in the enum
|
||||
// because we use it to calculate the size for the char* array.
|
||||
CSP_LAST_KEYWORD_VALUE,
|
||||
|
||||
// Putting CSP_HASH after the delimitor, because CSP_HASH is not a valid
|
||||
// keyword (hash uses e.g. sha256, sha512) but we use CSP_HASH internally
|
||||
// to identify allowed hashes in ::allows.
|
||||
CSP_HASH
|
||||
};
|
||||
|
||||
static const char* CSPStrKeywords[] = {
|
||||
"'self'", // CSP_SELF = 0
|
||||
"'unsafe-inline'", // CSP_UNSAFE_INLINE
|
||||
"'unsafe-eval'", // CSP_UNSAFE_EVAL
|
||||
"'none'", // CSP_NONE
|
||||
"'nonce-", // CSP_NONCE
|
||||
"require-sri-for", // CSP_REQUIRE_SRI_FOR
|
||||
"'strict-dynamic'" // CSP_STRICT_DYNAMIC
|
||||
// Remember: CSP_HASH is not supposed to be used
|
||||
// The keywords, in UTF-8 form.
|
||||
static const char* gCSPUTF8Keywords[] = {
|
||||
#define KEYWORD_UTF8_LITERAL(id_, string_) string_,
|
||||
FOR_EACH_CSP_KEYWORD(KEYWORD_UTF8_LITERAL)
|
||||
#undef KEYWORD_UTF8_LITERAL
|
||||
};
|
||||
|
||||
inline const char* CSP_EnumToKeyword(enum CSPKeyword aKey)
|
||||
{
|
||||
// Make sure all elements in enum CSPKeyword got added to CSPStrKeywords.
|
||||
static_assert((sizeof(CSPStrKeywords) / sizeof(CSPStrKeywords[0]) ==
|
||||
static_cast<uint32_t>(CSP_LAST_KEYWORD_VALUE)),
|
||||
"CSP_LAST_KEYWORD_VALUE does not match length of CSPStrKeywords");
|
||||
// The keywords, in UTF-16 form.
|
||||
static const char16_t* gCSPUTF16Keywords[] = {
|
||||
#define KEYWORD_UTF16_LITERAL(id_, string_) u"" string_,
|
||||
FOR_EACH_CSP_KEYWORD(KEYWORD_UTF16_LITERAL)
|
||||
#undef KEYWORD_UTF16_LITERAL
|
||||
};
|
||||
|
||||
if (static_cast<uint32_t>(aKey) < static_cast<uint32_t>(CSP_LAST_KEYWORD_VALUE)) {
|
||||
return CSPStrKeywords[static_cast<uint32_t>(aKey)];
|
||||
#undef FOR_EACH_CSP_KEYWORD
|
||||
|
||||
inline const char* CSP_EnumToUTF8Keyword(enum CSPKeyword aKey)
|
||||
{
|
||||
// Make sure all elements in enum CSPKeyword got added to gCSPUTF8Keywords.
|
||||
static_assert((sizeof(gCSPUTF8Keywords) / sizeof(gCSPUTF8Keywords[0]) ==
|
||||
CSP_LAST_KEYWORD_VALUE),
|
||||
"CSP_LAST_KEYWORD_VALUE != length(gCSPUTF8Keywords)");
|
||||
|
||||
if (static_cast<uint32_t>(aKey) <
|
||||
static_cast<uint32_t>(CSP_LAST_KEYWORD_VALUE)) {
|
||||
return gCSPUTF8Keywords[static_cast<uint32_t>(aKey)];
|
||||
}
|
||||
return "error: invalid keyword in CSP_EnumToKeyword";
|
||||
return "error: invalid keyword in CSP_EnumToUTF8Keyword";
|
||||
}
|
||||
|
||||
inline CSPKeyword CSP_KeywordToEnum(const nsAString& aKey)
|
||||
inline const char16_t* CSP_EnumToUTF16Keyword(enum CSPKeyword aKey)
|
||||
{
|
||||
// Make sure all elements in enum CSPKeyword got added to gCSPUTF16Keywords.
|
||||
static_assert((sizeof(gCSPUTF16Keywords) / sizeof(gCSPUTF16Keywords[0]) ==
|
||||
CSP_LAST_KEYWORD_VALUE),
|
||||
"CSP_LAST_KEYWORD_VALUE != length(gCSPUTF16Keywords)");
|
||||
|
||||
if (static_cast<uint32_t>(aKey) <
|
||||
static_cast<uint32_t>(CSP_LAST_KEYWORD_VALUE)) {
|
||||
return gCSPUTF16Keywords[static_cast<uint32_t>(aKey)];
|
||||
}
|
||||
return u"error: invalid keyword in CSP_EnumToUTF16Keyword";
|
||||
}
|
||||
|
||||
inline CSPKeyword CSP_UTF16KeywordToEnum(const nsAString& aKey)
|
||||
{
|
||||
nsString lowerKey = PromiseFlatString(aKey);
|
||||
ToLowerCase(lowerKey);
|
||||
|
||||
static_assert(CSP_LAST_KEYWORD_VALUE ==
|
||||
(sizeof(CSPStrKeywords) / sizeof(CSPStrKeywords[0])),
|
||||
"CSP_LAST_KEYWORD_VALUE does not match length of CSPStrKeywords");
|
||||
|
||||
for (uint32_t i = 0; i < CSP_LAST_KEYWORD_VALUE; i++) {
|
||||
if (lowerKey.EqualsASCII(CSPStrKeywords[i])) {
|
||||
if (lowerKey.Equals(gCSPUTF16Keywords[i])) {
|
||||
return static_cast<CSPKeyword>(i);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -263,9 +263,8 @@ class CSPValidator final : public nsCSPSrcVisitor {
|
|||
return true;
|
||||
|
||||
default:
|
||||
NS_ConvertASCIItoUTF16 keyword(CSP_EnumToKeyword(src.getKeyword()));
|
||||
|
||||
FormatError("csp.error.illegal-keyword", keyword);
|
||||
FormatError("csp.error.illegal-keyword",
|
||||
nsDependentString(CSP_EnumToUTF16Keyword(src.getKeyword())));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче