changeset: 312063:88bea96c802a user: Andrea Marchesini Date: Tue May 10 10:52:19 2016 +0200 summary: Bug 1267130 - Improve the URL segment calculation, r=valentin a=ritu diff -r 28dcecced055 -r 88bea96c802a netwerk/base/nsStandardURL.cpp --- a/netwerk/base/nsStandardURL.cpp Wed May 18 11:55:29 2016 +1200 +++ b/netwerk/base/nsStandardURL.cpp Tue May 10 10:52:19 2016 +0200 @@ -475,19 +475,28 @@ } uint32_t -nsStandardURL::AppendSegmentToBuf(char *buf, uint32_t i, const char *str, URLSegment &seg, const nsCString *escapedStr, bool useEscaped) +nsStandardURL::AppendSegmentToBuf(char *buf, uint32_t i, const char *str, + const URLSegment &segInput, URLSegment &segOutput, + const nsCString *escapedStr, + bool useEscaped, int32_t *diff) { - if (seg.mLen > 0) { + MOZ_ASSERT(segInput.mLen == segOutput.mLen); + + if (diff) *diff = 0; + + if (segInput.mLen > 0) { if (useEscaped) { - seg.mLen = escapedStr->Length(); - memcpy(buf + i, escapedStr->get(), seg.mLen); + MOZ_ASSERT(diff); + segOutput.mLen = escapedStr->Length(); + *diff = segOutput.mLen - segInput.mLen; + memcpy(buf + i, escapedStr->get(), segOutput.mLen); + } else { + memcpy(buf + i, str + segInput.mPos, segInput.mLen); } - else - memcpy(buf + i, str + seg.mPos, seg.mLen); - seg.mPos = i; - i += seg.mLen; + segOutput.mPos = i; + i += segOutput.mLen; } else { - seg.mPos = i; + segOutput.mPos = i; } return i; } @@ -598,6 +607,20 @@ } } + // We must take a copy of every single segment because they are pointing to + // the |spec| while we are changing their value, in case we must use + // encoded strings. + URLSegment username(mUsername); + URLSegment password(mPassword); + URLSegment host(mHost); + URLSegment path(mPath); + URLSegment filepath(mFilepath); + URLSegment directory(mDirectory); + URLSegment basename(mBasename); + URLSegment extension(mExtension); + URLSegment query(mQuery); + URLSegment ref(mRef); + // // generate the normalized URL string // @@ -607,9 +630,10 @@ char *buf; mSpec.BeginWriting(buf); uint32_t i = 0; + int32_t diff = 0; if (mScheme.mLen > 0) { - i = AppendSegmentToBuf(buf, i, spec, mScheme); + i = AppendSegmentToBuf(buf, i, spec, mScheme, mScheme); net_ToLowerCase(buf + mScheme.mPos, mScheme.mLen); i = AppendToBuf(buf, i, "://", 3); } @@ -619,15 +643,22 @@ // append authority if (mUsername.mLen > 0) { - i = AppendSegmentToBuf(buf, i, spec, mUsername, &encUsername, useEncUsername); - if (mPassword.mLen >= 0) { + i = AppendSegmentToBuf(buf, i, spec, username, mUsername, + &encUsername, useEncUsername, &diff); + ShiftFromPassword(diff); + if (password.mLen >= 0) { buf[i++] = ':'; - i = AppendSegmentToBuf(buf, i, spec, mPassword, &encPassword, useEncPassword); + i = AppendSegmentToBuf(buf, i, spec, password, mPassword, + &encPassword, useEncPassword, &diff); + ShiftFromHost(diff); } buf[i++] = '@'; } - if (mHost.mLen > 0) { - i = AppendSegmentToBuf(buf, i, spec, mHost, &encHost, useEncHost); + if (host.mLen > 0) { + i = AppendSegmentToBuf(buf, i, spec, host, mHost, &encHost, useEncHost, + &diff); + ShiftFromPath(diff); + net_ToLowerCase(buf + mHost.mPos, mHost.mLen); MOZ_ASSERT(mPort >= -1, "Invalid negative mPort"); if (mPort != -1 && mPort != mDefaultPort) { @@ -652,21 +683,23 @@ } else { uint32_t leadingSlash = 0; - if (spec[mPath.mPos] != '/') { + if (spec[path.mPos] != '/') { LOG(("adding leading slash to path\n")); leadingSlash = 1; buf[i++] = '/'; // basename must exist, even if empty (bugs 113508, 429347) if (mBasename.mLen == -1) { - mBasename.mPos = i; - mBasename.mLen = 0; + mBasename.mPos = basename.mPos = i; + mBasename.mLen = basename.mLen = 0; } } // record corrected (file)path starting position mPath.mPos = mFilepath.mPos = i - leadingSlash; - i = AppendSegmentToBuf(buf, i, spec, mDirectory, &encDirectory, useEncDirectory); + i = AppendSegmentToBuf(buf, i, spec, directory, mDirectory, + &encDirectory, useEncDirectory, &diff); + ShiftFromBasename(diff); // the directory must end with a '/' if (buf[i-1] != '/') { @@ -674,7 +707,9 @@ mDirectory.mLen++; } - i = AppendSegmentToBuf(buf, i, spec, mBasename, &encBasename, useEncBasename); + i = AppendSegmentToBuf(buf, i, spec, basename, mBasename, + &encBasename, useEncBasename, &diff); + ShiftFromExtension(diff); // make corrections to directory segment if leadingSlash if (leadingSlash) { @@ -687,18 +722,24 @@ if (mExtension.mLen >= 0) { buf[i++] = '.'; - i = AppendSegmentToBuf(buf, i, spec, mExtension, &encExtension, useEncExtension); + i = AppendSegmentToBuf(buf, i, spec, extension, mExtension, + &encExtension, useEncExtension, &diff); + ShiftFromQuery(diff); } // calculate corrected filepath length mFilepath.mLen = i - mFilepath.mPos; if (mQuery.mLen >= 0) { buf[i++] = '?'; - i = AppendSegmentToBuf(buf, i, spec, mQuery, &encQuery, useEncQuery); + i = AppendSegmentToBuf(buf, i, spec, query, mQuery, + &encQuery, useEncQuery, + &diff); + ShiftFromRef(diff); } if (mRef.mLen >= 0) { buf[i++] = '#'; - i = AppendSegmentToBuf(buf, i, spec, mRef, &encRef, useEncRef); + i = AppendSegmentToBuf(buf, i, spec, ref, mRef, &encRef, useEncRef, + &diff); } // calculate corrected path length mPath.mLen = i - mPath.mPos; @@ -953,6 +994,39 @@ #undef GOT_PREF } +#define SHIFT_FROM(name, what) \ +void \ +nsStandardURL::name(int32_t diff) \ +{ \ + if (!diff) return; \ + if (what.mLen >= 0) { \ + CheckedInt pos = what.mPos; \ + pos += diff; \ + MOZ_ASSERT(pos.isValid()); \ + what.mPos = pos.value(); \ + } + +#define SHIFT_FROM_NEXT(name, what, next) \ + SHIFT_FROM(name, what) \ + next(diff); \ +} + +#define SHIFT_FROM_LAST(name, what) \ + SHIFT_FROM(name, what) \ +} + +SHIFT_FROM_NEXT(ShiftFromAuthority, mAuthority, ShiftFromUsername) +SHIFT_FROM_NEXT(ShiftFromUsername, mUsername, ShiftFromPassword) +SHIFT_FROM_NEXT(ShiftFromPassword, mPassword, ShiftFromHost) +SHIFT_FROM_NEXT(ShiftFromHost, mHost, ShiftFromPath) +SHIFT_FROM_NEXT(ShiftFromPath, mPath, ShiftFromFilepath) +SHIFT_FROM_NEXT(ShiftFromFilepath, mFilepath, ShiftFromDirectory) +SHIFT_FROM_NEXT(ShiftFromDirectory, mDirectory, ShiftFromBasename) +SHIFT_FROM_NEXT(ShiftFromBasename, mBasename, ShiftFromExtension) +SHIFT_FROM_NEXT(ShiftFromExtension, mExtension, ShiftFromQuery) +SHIFT_FROM_NEXT(ShiftFromQuery, mQuery, ShiftFromRef) +SHIFT_FROM_LAST(ShiftFromRef, mRef) + //---------------------------------------------------------------------------- // nsStandardURL::nsISupports //---------------------------------------------------------------------------- diff -r 28dcecced055 -r 88bea96c802a netwerk/base/nsStandardURL.h --- a/netwerk/base/nsStandardURL.h Wed May 18 11:55:29 2016 +1200 +++ b/netwerk/base/nsStandardURL.h Tue May 10 10:52:19 2016 +0200 @@ -77,6 +77,7 @@ URLSegment() : mPos(0), mLen(-1) {} URLSegment(uint32_t pos, int32_t len) : mPos(pos), mLen(len) {} + URLSegment(const URLSegment& aCopy) : mPos(aCopy.mPos), mLen(aCopy.mLen) {} void Reset() { mPos = 0; mLen = -1; } // Merge another segment following this one to it if they're contiguous // Assumes we have something like "foo;bar" where this object is 'foo' and right @@ -177,7 +178,10 @@ bool NormalizeIDN(const nsCSubstring &host, nsCString &result); void CoalescePath(netCoalesceFlags coalesceFlag, char *path); - uint32_t AppendSegmentToBuf(char *, uint32_t, const char *, URLSegment &, const nsCString *esc=nullptr, bool useEsc = false); + uint32_t AppendSegmentToBuf(char *, uint32_t, const char *, + const URLSegment &input, URLSegment &output, + const nsCString *esc=nullptr, + bool useEsc = false, int32_t* diff = nullptr); uint32_t AppendToBuf(char *, uint32_t, const char *, uint32_t); nsresult BuildNormalizedSpec(const char *spec); @@ -216,17 +220,17 @@ const nsDependentCSubstring Ref() { return Segment(mRef); } // shift the URLSegments to the right by diff - void ShiftFromAuthority(int32_t diff) { mAuthority.mPos += diff; ShiftFromUsername(diff); } - void ShiftFromUsername(int32_t diff) { mUsername.mPos += diff; ShiftFromPassword(diff); } - void ShiftFromPassword(int32_t diff) { mPassword.mPos += diff; ShiftFromHost(diff); } - void ShiftFromHost(int32_t diff) { mHost.mPos += diff; ShiftFromPath(diff); } - void ShiftFromPath(int32_t diff) { mPath.mPos += diff; ShiftFromFilepath(diff); } - void ShiftFromFilepath(int32_t diff) { mFilepath.mPos += diff; ShiftFromDirectory(diff); } - void ShiftFromDirectory(int32_t diff) { mDirectory.mPos += diff; ShiftFromBasename(diff); } - void ShiftFromBasename(int32_t diff) { mBasename.mPos += diff; ShiftFromExtension(diff); } - void ShiftFromExtension(int32_t diff) { mExtension.mPos += diff; ShiftFromQuery(diff); } - void ShiftFromQuery(int32_t diff) { mQuery.mPos += diff; ShiftFromRef(diff); } - void ShiftFromRef(int32_t diff) { mRef.mPos += diff; } + void ShiftFromAuthority(int32_t diff); + void ShiftFromUsername(int32_t diff); + void ShiftFromPassword(int32_t diff); + void ShiftFromHost(int32_t diff); + void ShiftFromPath(int32_t diff); + void ShiftFromFilepath(int32_t diff); + void ShiftFromDirectory(int32_t diff); + void ShiftFromBasename(int32_t diff); + void ShiftFromExtension(int32_t diff); + void ShiftFromQuery(int32_t diff); + void ShiftFromRef(int32_t diff); // fastload helper functions nsresult ReadSegment(nsIBinaryInputStream *, URLSegment &);