зеркало из https://github.com/mozilla/gecko-dev.git
Additional precautions against potential buffer overruns. b=307259 r=darin sr=dveditz
This commit is contained in:
Родитель
03df34dd12
Коммит
e7099d7048
|
@ -170,8 +170,10 @@ PRInt32 nsStandardURL::
|
|||
nsSegmentEncoder::EncodeSegmentCount(const char *str,
|
||||
const URLSegment &seg,
|
||||
PRInt16 mask,
|
||||
nsAFlatCString &result)
|
||||
nsAFlatCString &result,
|
||||
PRBool &appended)
|
||||
{
|
||||
appended = PR_FALSE;
|
||||
if (!str)
|
||||
return 0;
|
||||
PRInt32 len = 0;
|
||||
|
@ -203,11 +205,14 @@ nsSegmentEncoder::EncodeSegmentCount(const char *str,
|
|||
PRUint32 initLen = result.Length();
|
||||
|
||||
// now perform any required escaping
|
||||
if (NS_EscapeURL(str + pos, len, mask | escapeFlags, result))
|
||||
if (NS_EscapeURL(str + pos, len, mask | escapeFlags, result)) {
|
||||
len = result.Length() - initLen;
|
||||
appended = PR_TRUE;
|
||||
}
|
||||
else if (str == encBuf.get()) {
|
||||
result += encBuf; // append only!!
|
||||
len = encBuf.Length();
|
||||
appended = PR_TRUE;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
|
@ -219,13 +224,11 @@ nsSegmentEncoder::EncodeSegment(const nsASingleFragmentCString &str,
|
|||
nsAFlatCString &result)
|
||||
{
|
||||
const char *text;
|
||||
PRUint32 resultLen = result.Length();
|
||||
EncodeSegmentCount(str.BeginReading(text), URLSegment(0, str.Length()), mask, result);
|
||||
// since EncodeSegmentCount appends to result, we must check whether its length grew
|
||||
if (result.Length() > resultLen)
|
||||
PRBool encoded;
|
||||
EncodeSegmentCount(str.BeginReading(text), URLSegment(0, str.Length()), mask, result, encoded);
|
||||
if (encoded)
|
||||
return result;
|
||||
else
|
||||
return str;
|
||||
return str;
|
||||
}
|
||||
|
||||
PRBool nsStandardURL::
|
||||
|
@ -395,14 +398,14 @@ nsStandardURL::NormalizeIDN(const nsCSubstring &host, nsCString &result)
|
|||
PRBool isACE;
|
||||
if (gIDN &&
|
||||
NS_SUCCEEDED(gIDN->IsACE(host, &isACE)) && isACE &&
|
||||
NS_SUCCEEDED(ACEtoUTF8(host, result))) {
|
||||
NS_SUCCEEDED(ACEtoDisplayIDN(host, result))) {
|
||||
mHostEncoding = eEncoding_UTF8;
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mHostEncoding = eEncoding_UTF8;
|
||||
if (gIDN && NS_SUCCEEDED(NormalizeUTF8(host, result))) {
|
||||
if (gIDN && NS_SUCCEEDED(UTF8toDisplayIDN(host, result))) {
|
||||
// normalization could result in an ASCII only hostname
|
||||
if (IsASCII(result))
|
||||
mHostEncoding = eEncoding_ASCII;
|
||||
|
@ -429,10 +432,10 @@ nsStandardURL::CoalescePath(netCoalesceFlags coalesceFlag, char *path)
|
|||
}
|
||||
|
||||
PRUint32
|
||||
nsStandardURL::AppendSegmentToBuf(char *buf, PRUint32 i, const char *str, URLSegment &seg, const nsCString *escapedStr)
|
||||
nsStandardURL::AppendSegmentToBuf(char *buf, PRUint32 i, const char *str, URLSegment &seg, const nsCString *escapedStr, PRBool useEscaped)
|
||||
{
|
||||
if (seg.mLen > 0) {
|
||||
if (escapedStr && !escapedStr->IsEmpty()) {
|
||||
if (useEscaped) {
|
||||
seg.mLen = escapedStr->Length();
|
||||
memcpy(buf + i, escapedStr->get(), seg.mLen);
|
||||
}
|
||||
|
@ -464,16 +467,10 @@ nsStandardURL::BuildNormalizedSpec(const char *spec)
|
|||
|
||||
// buffers for holding escaped url segments (these will remain empty unless
|
||||
// escaping is required).
|
||||
nsCAutoString encUsername;
|
||||
nsCAutoString encPassword;
|
||||
nsCAutoString encHost;
|
||||
PRBool useEncHost;
|
||||
nsCAutoString encDirectory;
|
||||
nsCAutoString encBasename;
|
||||
nsCAutoString encExtension;
|
||||
nsCAutoString encParam;
|
||||
nsCAutoString encQuery;
|
||||
nsCAutoString encRef;
|
||||
nsCAutoString encUsername, encPassword, encHost, encDirectory,
|
||||
encBasename, encExtension, encParam, encQuery, encRef;
|
||||
PRBool useEncUsername, useEncPassword, useEncHost, useEncDirectory,
|
||||
useEncBasename, useEncExtension, useEncParam, useEncQuery, useEncRef;
|
||||
|
||||
//
|
||||
// escape each URL segment, if necessary, and calculate approximate normalized
|
||||
|
@ -490,14 +487,14 @@ nsStandardURL::BuildNormalizedSpec(const char *spec)
|
|||
// appropriate encoding.
|
||||
{
|
||||
GET_SEGMENT_ENCODER(encoder);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mUsername, esc_Username, encUsername);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mPassword, esc_Password, encPassword);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mDirectory, esc_Directory, encDirectory);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mBasename, esc_FileBaseName, encBasename);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mExtension, esc_FileExtension, encExtension);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mParam, esc_Param, encParam);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mQuery, esc_Query, encQuery);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mRef, esc_Ref, encRef);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mUsername, esc_Username, encUsername, useEncUsername);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mPassword, esc_Password, encPassword, useEncPassword);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mDirectory, esc_Directory, encDirectory, useEncDirectory);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mBasename, esc_FileBaseName, encBasename, useEncBasename);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mExtension, esc_FileExtension, encExtension, useEncExtension);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mParam, esc_Param, encParam, useEncParam);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mQuery, esc_Query, encQuery, useEncQuery);
|
||||
approxLen += encoder.EncodeSegmentCount(spec, mRef, esc_Ref, encRef, useEncRef);
|
||||
}
|
||||
|
||||
// do not escape the hostname, if IPv6 address literal, mHost will
|
||||
|
@ -532,21 +529,15 @@ nsStandardURL::BuildNormalizedSpec(const char *spec)
|
|||
|
||||
// append authority
|
||||
if (mUsername.mLen > 0) {
|
||||
i = AppendSegmentToBuf(buf, i, spec, mUsername, &encUsername);
|
||||
i = AppendSegmentToBuf(buf, i, spec, mUsername, &encUsername, useEncUsername);
|
||||
if (mPassword.mLen >= 0) {
|
||||
buf[i++] = ':';
|
||||
i = AppendSegmentToBuf(buf, i, spec, mPassword, &encPassword);
|
||||
i = AppendSegmentToBuf(buf, i, spec, mPassword, &encPassword, useEncPassword);
|
||||
}
|
||||
buf[i++] = '@';
|
||||
}
|
||||
if (mHost.mLen > 0) {
|
||||
if (useEncHost) {
|
||||
mHost.mPos = i;
|
||||
mHost.mLen = encHost.Length();
|
||||
i = AppendToBuf(buf, i, encHost.get(), mHost.mLen);
|
||||
}
|
||||
else
|
||||
i = AppendSegmentToBuf(buf, i, spec, mHost);
|
||||
i = AppendSegmentToBuf(buf, i, spec, mHost, &encHost, useEncHost);
|
||||
net_ToLowerCase(buf + mHost.mPos, mHost.mLen);
|
||||
if (mPort != -1 && mPort != mDefaultPort) {
|
||||
nsCAutoString portbuf;
|
||||
|
@ -580,7 +571,7 @@ nsStandardURL::BuildNormalizedSpec(const char *spec)
|
|||
// record corrected (file)path starting position
|
||||
mPath.mPos = mFilepath.mPos = i - leadingSlash;
|
||||
|
||||
i = AppendSegmentToBuf(buf, i, spec, mDirectory, &encDirectory);
|
||||
i = AppendSegmentToBuf(buf, i, spec, mDirectory, &encDirectory, useEncDirectory);
|
||||
|
||||
// the directory must end with a '/'
|
||||
if (buf[i-1] != '/') {
|
||||
|
@ -588,7 +579,7 @@ nsStandardURL::BuildNormalizedSpec(const char *spec)
|
|||
mDirectory.mLen++;
|
||||
}
|
||||
|
||||
i = AppendSegmentToBuf(buf, i, spec, mBasename, &encBasename);
|
||||
i = AppendSegmentToBuf(buf, i, spec, mBasename, &encBasename, useEncBasename);
|
||||
|
||||
// make corrections to directory segment if leadingSlash
|
||||
if (leadingSlash) {
|
||||
|
@ -601,22 +592,22 @@ nsStandardURL::BuildNormalizedSpec(const char *spec)
|
|||
|
||||
if (mExtension.mLen >= 0) {
|
||||
buf[i++] = '.';
|
||||
i = AppendSegmentToBuf(buf, i, spec, mExtension, &encExtension);
|
||||
i = AppendSegmentToBuf(buf, i, spec, mExtension, &encExtension, useEncExtension);
|
||||
}
|
||||
// calculate corrected filepath length
|
||||
mFilepath.mLen = i - mFilepath.mPos;
|
||||
|
||||
if (mParam.mLen >= 0) {
|
||||
buf[i++] = ';';
|
||||
i = AppendSegmentToBuf(buf, i, spec, mParam, &encParam);
|
||||
i = AppendSegmentToBuf(buf, i, spec, mParam, &encParam, useEncParam);
|
||||
}
|
||||
if (mQuery.mLen >= 0) {
|
||||
buf[i++] = '?';
|
||||
i = AppendSegmentToBuf(buf, i, spec, mQuery, &encQuery);
|
||||
i = AppendSegmentToBuf(buf, i, spec, mQuery, &encQuery, useEncQuery);
|
||||
}
|
||||
if (mRef.mLen >= 0) {
|
||||
buf[i++] = '#';
|
||||
i = AppendSegmentToBuf(buf, i, spec, mRef, &encRef);
|
||||
i = AppendSegmentToBuf(buf, i, spec, mRef, &encRef, useEncRef);
|
||||
}
|
||||
// calculate corrected path length
|
||||
mPath.mLen = i - mPath.mPos;
|
||||
|
@ -859,7 +850,7 @@ nsStandardURL::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
|||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsStandardURL::ACEtoUTF8(const nsCSubstring &host, nsCString &result)
|
||||
nsStandardURL::ACEtoDisplayIDN(const nsCSubstring &host, nsCString &result)
|
||||
{
|
||||
if (gShowPunycode || !IsInWhitelist(host)) {
|
||||
result = host;
|
||||
|
@ -870,7 +861,7 @@ nsStandardURL::ACEtoUTF8(const nsCSubstring &host, nsCString &result)
|
|||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsStandardURL::NormalizeUTF8(const nsCSubstring &host, nsCString &result)
|
||||
nsStandardURL::UTF8toDisplayIDN(const nsCSubstring &host, nsCString &result)
|
||||
{
|
||||
if (gShowPunycode || !IsInWhitelist(host))
|
||||
return gIDN->ConvertUTF8toACE(host, result);
|
||||
|
@ -1221,18 +1212,20 @@ nsStandardURL::SetUserPass(const nsACString &input)
|
|||
nsCAutoString buf;
|
||||
if (usernameLen > 0) {
|
||||
GET_SEGMENT_ENCODER(encoder);
|
||||
PRBool ignoredOut;
|
||||
usernameLen = encoder.EncodeSegmentCount(userpass.get(),
|
||||
URLSegment(usernamePos,
|
||||
usernameLen),
|
||||
esc_Username | esc_AlwaysCopy,
|
||||
buf);
|
||||
buf, ignoredOut);
|
||||
if (passwordLen >= 0) {
|
||||
buf.Append(':');
|
||||
passwordLen = encoder.EncodeSegmentCount(userpass.get(),
|
||||
URLSegment(passwordPos,
|
||||
passwordLen),
|
||||
esc_Password |
|
||||
esc_AlwaysCopy, buf);
|
||||
esc_AlwaysCopy, buf,
|
||||
ignoredOut);
|
||||
}
|
||||
if (mUsername.mLen < 0)
|
||||
buf.Append('@');
|
||||
|
@ -2183,9 +2176,11 @@ nsStandardURL::SetQuery(const nsACString &input)
|
|||
|
||||
// encode query if necessary
|
||||
nsCAutoString buf;
|
||||
PRBool encoded;
|
||||
GET_SEGMENT_ENCODER(encoder);
|
||||
encoder.EncodeSegmentCount(query, URLSegment(0, queryLen), esc_Query, buf);
|
||||
if (!buf.IsEmpty()) {
|
||||
encoder.EncodeSegmentCount(query, URLSegment(0, queryLen), esc_Query,
|
||||
buf, encoded);
|
||||
if (encoded) {
|
||||
query = buf.get();
|
||||
queryLen = buf.Length();
|
||||
}
|
||||
|
@ -2241,9 +2236,11 @@ nsStandardURL::SetRef(const nsACString &input)
|
|||
|
||||
// encode ref if necessary
|
||||
nsCAutoString buf;
|
||||
PRBool encoded;
|
||||
GET_SEGMENT_ENCODER(encoder);
|
||||
encoder.EncodeSegmentCount(ref, URLSegment(0, refLen), esc_Ref, buf);
|
||||
if (!buf.IsEmpty()) {
|
||||
encoder.EncodeSegmentCount(ref, URLSegment(0, refLen), esc_Ref,
|
||||
buf, encoded);
|
||||
if (encoded) {
|
||||
ref = buf.get();
|
||||
refLen = buf.Length();
|
||||
}
|
||||
|
@ -2311,17 +2308,20 @@ nsStandardURL::SetFileName(const nsACString &input)
|
|||
}
|
||||
else {
|
||||
nsCAutoString newFilename;
|
||||
PRBool ignoredOut;
|
||||
GET_SEGMENT_ENCODER(encoder);
|
||||
basename.mLen = encoder.EncodeSegmentCount(filename, basename,
|
||||
esc_FileBaseName |
|
||||
esc_AlwaysCopy,
|
||||
newFilename);
|
||||
newFilename,
|
||||
ignoredOut);
|
||||
if (extension.mLen >= 0) {
|
||||
newFilename.Append('.');
|
||||
extension.mLen = encoder.EncodeSegmentCount(filename, extension,
|
||||
esc_FileExtension |
|
||||
esc_AlwaysCopy,
|
||||
newFilename);
|
||||
newFilename,
|
||||
ignoredOut);
|
||||
}
|
||||
|
||||
if (mBasename.mLen < 0) {
|
||||
|
|
|
@ -124,7 +124,8 @@ public: /* internal -- HPUX compiler can't handle this being private */
|
|||
PRInt32 EncodeSegmentCount(const char *str,
|
||||
const URLSegment &segment,
|
||||
PRInt16 mask,
|
||||
nsAFlatCString &buf);
|
||||
nsAFlatCString &buf,
|
||||
PRBool& appended);
|
||||
|
||||
// Encode the given string if necessary, and return a reference to
|
||||
// the encoded string. Returns a reference to |buf| if encoding
|
||||
|
@ -159,7 +160,7 @@ private:
|
|||
PRBool NormalizeIDN(const nsCSubstring &host, nsCString &result);
|
||||
void CoalescePath(netCoalesceFlags coalesceFlag, char *path);
|
||||
|
||||
PRUint32 AppendSegmentToBuf(char *, PRUint32, const char *, URLSegment &, const nsCString *esc=nsnull);
|
||||
PRUint32 AppendSegmentToBuf(char *, PRUint32, const char *, URLSegment &, const nsCString *esc=nsnull, PRBool useEsc = PR_FALSE);
|
||||
PRUint32 AppendToBuf(char *, PRUint32, const char *, PRUint32);
|
||||
|
||||
nsresult BuildNormalizedSpec(const char *spec);
|
||||
|
@ -219,8 +220,8 @@ private:
|
|||
static void PrefsChanged(nsIPrefBranch *prefs, const char *pref);
|
||||
|
||||
// IDN routines
|
||||
static nsresult ACEtoUTF8(const nsCSubstring &in, nsCString &out);
|
||||
static nsresult NormalizeUTF8(const nsCSubstring &in, nsCString &out);
|
||||
static nsresult ACEtoDisplayIDN(const nsCSubstring &in, nsCString &out);
|
||||
static nsresult UTF8toDisplayIDN(const nsCSubstring &in, nsCString &out);
|
||||
static PRBool IsInWhitelist(const nsCSubstring &host);
|
||||
|
||||
// mSpec contains the normalized version of the URL spec (UTF-8 encoded).
|
||||
|
|
Загрузка…
Ссылка в новой задаче