diff --git a/intl/unicharutil/src/nsSaveAsCharset.cpp b/intl/unicharutil/src/nsSaveAsCharset.cpp index bf7d7ecd1b4..92596cdb06d 100644 --- a/intl/unicharutil/src/nsSaveAsCharset.cpp +++ b/intl/unicharutil/src/nsSaveAsCharset.cpp @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -127,6 +128,8 @@ nsSaveAsCharset::GetCharset(char * *aCharset) ///////////////////////////////////////////////////////////////////////////////////////// +#define RESERVE_FALLBACK_BYTES 512 + // do the fallback, reallocate the buffer if necessary // need to pass destination buffer info (size, current position and estimation of rest of the conversion) NS_IMETHODIMP @@ -144,14 +147,16 @@ nsSaveAsCharset::HandleFallBack(uint32_t character, char **outString, int32_t *b // reallocate if the buffer is not large enough if ((tempLen + estimatedLength) >= (*bufferLength - *currentPos)) { - char *temp = (char *) PR_Realloc(*outString, *bufferLength + tempLen); + int32_t addLength = tempLen + RESERVE_FALLBACK_BYTES; + // + 1 is for the terminating NUL, don't add that to bufferLength + char *temp = (char *) PR_Realloc(*outString, *bufferLength + addLength + 1); if (temp) { // adjust length/pointer after realloc - *bufferLength += tempLen; + *bufferLength += addLength; *outString = temp; } else { *outString = nullptr; - *bufferLength =0; + *bufferLength = 0; return NS_ERROR_OUT_OF_MEMORY; } } @@ -180,12 +185,19 @@ nsSaveAsCharset::DoCharsetConversion(const PRUnichar *inString, char **outString rv = mEncoder->GetMaxLength(inString, inStringLength, &dstLength); if (NS_FAILED(rv)) return rv; - bufferLength = dstLength + 512; // reserve 512 byte for fallback. - char *dstPtr = (char *) PR_Malloc(bufferLength); + bufferLength = dstLength + RESERVE_FALLBACK_BYTES; // extra bytes for fallback + // + 1 is for the terminating NUL -- we don't add that to bufferLength so that + // we can always write dstPtr[pos2] = '\0' even when the encoder filled the + // buffer. + char *dstPtr = (char *) PR_Malloc(bufferLength + 1); + if (!dstPtr) { + return NS_ERROR_OUT_OF_MEMORY; + } for (pos1 = 0, pos2 = 0; pos1 < inStringLength;) { // convert from unicode dstLength = bufferLength - pos2; + NS_ASSERTION(dstLength >= 0, "out of bounds write"); rv = mEncoder->Convert(&inString[pos1], &srcLength, &dstPtr[pos2], &dstLength); pos1 += srcLength ? srcLength : 1;