Commit 948922a9 authored by Norisz Fay's avatar Norisz Fay
Browse files

Backed out changeset 2c6bb36b0667 (bug 1170668) for causing build bustages on...

Backed out changeset 2c6bb36b0667 (bug 1170668) for causing build bustages on TestShortRead.cpp CLOSED TREE
parent e11a3f65
Loading
Loading
Loading
Loading
+62 −79
Original line number Diff line number Diff line
@@ -105,38 +105,39 @@ nsConverterInputStream::ReadSegments(nsWriteUnicharSegmentFun aWriter,
                                     void* aClosure, uint32_t aCount,
                                     uint32_t* aReadCount) {
  NS_ASSERTION(mUnicharDataLength >= mUnicharDataOffset, "unsigned madness");
  uint32_t codeUnitsToWrite = mUnicharDataLength - mUnicharDataOffset;
  if (0 == codeUnitsToWrite) {
  uint32_t bytesToWrite = mUnicharDataLength - mUnicharDataOffset;
  nsresult rv;
  if (0 == bytesToWrite) {
    // Fill the unichar buffer
    codeUnitsToWrite = Fill(&mLastErrorCode);
    if (codeUnitsToWrite == 0) {
    bytesToWrite = Fill(&rv);
    if (bytesToWrite <= 0) {
      *aReadCount = 0;
      return mLastErrorCode;
      return rv;
    }
    if (NS_FAILED(rv)) {
      return rv;
    }

  if (codeUnitsToWrite > aCount) {
    codeUnitsToWrite = aCount;
  }

  uint32_t codeUnitsWritten;
  uint32_t totalCodeUnitsWritten = 0;
  if (bytesToWrite > aCount) bytesToWrite = aCount;

  uint32_t bytesWritten;
  uint32_t totalBytesWritten = 0;

  while (codeUnitsToWrite) {
    nsresult rv =
        aWriter(this, aClosure, mUnicharData.Elements() + mUnicharDataOffset,
                totalCodeUnitsWritten, codeUnitsToWrite, &codeUnitsWritten);
  while (bytesToWrite) {
    rv = aWriter(this, aClosure, mUnicharData.Elements() + mUnicharDataOffset,
                 totalBytesWritten, bytesToWrite, &bytesWritten);
    if (NS_FAILED(rv)) {
      // don't propagate errors to the caller
      break;
    }

    codeUnitsToWrite -= codeUnitsWritten;
    totalCodeUnitsWritten += codeUnitsWritten;
    mUnicharDataOffset += codeUnitsWritten;
    bytesToWrite -= bytesWritten;
    totalBytesWritten += bytesWritten;
    mUnicharDataOffset += bytesWritten;
  }

  *aReadCount = totalCodeUnitsWritten;
  *aReadCount = totalBytesWritten;

  return NS_OK;
}
@@ -165,7 +166,7 @@ nsConverterInputStream::ReadString(uint32_t aCount, nsAString& aString,
}

uint32_t nsConverterInputStream::Fill(nsresult* aErrorCode) {
  if (!mInput) {
  if (nullptr == mInput) {
    // We already closed the stream!
    *aErrorCode = NS_BASE_STREAM_CLOSED;
    return 0;
@@ -178,19 +179,6 @@ uint32_t nsConverterInputStream::Fill(nsresult* aErrorCode) {
    return 0;
  }

  // mUnicharData.Length() is the buffer length, not the fill status.
  // mUnicharDataLength reflects the current fill status.
  mUnicharDataLength = 0;
  // Whenever we convert, mUnicharData is logically empty.
  mUnicharDataOffset = 0;

  // Continue trying to read from the source stream until we successfully decode
  // a character or encounter an error, as returning `0` here implies that the
  // stream is complete.
  //
  // If the converter has been cleared, we've fully consumed the stream, and
  // want to report EOF.
  while (mUnicharDataLength == 0 && mConverter) {
  // We assume a many to one conversion and are using equal sizes for
  // the two buffers.  However if an error happens at the very start
  // of a byte buffer we may end up in a situation where n bytes lead
@@ -199,51 +187,46 @@ uint32_t nsConverterInputStream::Fill(nsresult* aErrorCode) {

  uint32_t nb;
  *aErrorCode = NS_FillArray(mByteData, mInput, mLeftOverBytes, &nb);
    if (NS_FAILED(*aErrorCode)) {
  if (nb == 0 && mLeftOverBytes == 0) {
    // No more data
    *aErrorCode = NS_OK;
    return 0;
  }

  NS_ASSERTION(uint32_t(nb) + mLeftOverBytes == mByteData.Length(),
               "mByteData is lying to us somewhere");

    // If `NS_FillArray` failed to read any new bytes, this is the last read,
    // and we're at the end of the stream.
    bool last = (nb == 0);

  // Now convert as much of the byte buffer to unicode as possible
  auto src = AsBytes(Span(mByteData));
  auto dst = Span(mUnicharData);

  // mUnicharData.Length() is the buffer length, not the fill status.
  // mUnicharDataLength reflects the current fill status.
  mUnicharDataLength = 0;
  // Whenever we convert, mUnicharData is logically empty.
  mUnicharDataOffset = 0;
  // Truncation from size_t to uint32_t below is OK, because the sizes
  // are bounded by the lengths of mByteData and mUnicharData.
  uint32_t result;
  size_t read;
  size_t written;
  // The design of this class is fundamentally bogus in that trailing
  // errors are ignored. Always passing false as the last argument to
  // Decode* calls below.
  if (mErrorsAreFatal) {
    std::tie(result, read, written) =
          mConverter->DecodeToUTF16WithoutReplacement(src, dst, last);
        mConverter->DecodeToUTF16WithoutReplacement(src, dst, false);
  } else {
    std::tie(result, read, written, std::ignore) =
          mConverter->DecodeToUTF16(src, dst, last);
        mConverter->DecodeToUTF16(src, dst, false);
  }
  mLeftOverBytes = mByteData.Length() - read;
  mUnicharDataLength = written;
    // Clear `mConverter` if we reached the end of the stream, as we can't
    // call methods on it anymore. This will also signal EOF to the caller
    // through the loop condition.
    if (last) {
      MOZ_ASSERT(mLeftOverBytes == 0,
                 "Failed to read all bytes on the last pass?");
      mConverter = nullptr;
    }
    // If we got a decode error, we're done.
    if (result != kInputEmpty && result != kOutputFull) {
  if (result == kInputEmpty || result == kOutputFull) {
    *aErrorCode = NS_OK;
  } else {
    MOZ_ASSERT(mErrorsAreFatal, "How come DecodeToUTF16() reported error?");
    *aErrorCode = NS_ERROR_UDEC_ILLEGALINPUT;
      return 0;
    }
  }
  *aErrorCode = NS_OK;
  return mUnicharDataLength;
}

+0 −106
Original line number Diff line number Diff line
/* -*- 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/. */

#include "gtest/gtest.h"
#include "mozilla/ErrorNames.h"
#include "nsCOMPtr.h"
#include "nsConverterInputStream.h"
#include "nsIInputStream.h"
#include "nsISupports.h"
#include "nsStringStream.h"

namespace {

class ShortReadWrapper final : public nsIInputStream {
 public:
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSIINPUTSTREAM

  template <size_t N>
  ShortReadWrapper(const uint32_t (&aShortReads)[N],
                   nsIInputStream* aBaseStream)
      : mShortReadIter(std::begin(aShortReads)),
        mShortReadEnd(std::end(aShortReads)),
        mBaseStream(aBaseStream) {}

  ShortReadWrapper(const ShortReadWrapper&) = delete;
  ShortReadWrapper& operator=(const ShortReadWrapper&) = delete;

 private:
  ~ShortReadWrapper() = default;

  const uint32_t* mShortReadIter;
  const uint32_t* mShortReadEnd;
  nsCOMPtr<nsIInputStream> mBaseStream;
};

NS_IMPL_ISUPPORTS(ShortReadWrapper, nsIInputStream)

NS_IMETHODIMP
ShortReadWrapper::Close() { return mBaseStream->Close(); }

NS_IMETHODIMP
ShortReadWrapper::Available(uint64_t* aAvailable) {
  nsresult rv = mBaseStream->Available(aAvailable);
  NS_ENSURE_SUCCESS(rv, rv);

  if (mShortReadIter != mShortReadEnd) {
    *aAvailable = std::min(uint64_t(*mShortReadIter), *aAvailable);
  }
  return NS_OK;
}

NS_IMETHODIMP
ShortReadWrapper::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) {
  if (mShortReadIter != mShortReadEnd) {
    aCount = std::min(*mShortReadIter, aCount);
  }

  nsresult rv = mBaseStream->Read(aBuf, aCount, _retval);
  if (NS_SUCCEEDED(rv) && mShortReadIter != mShortReadEnd) {
    ++mShortReadIter;
  }
  return rv;
}

NS_IMETHODIMP
ShortReadWrapper::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
                               uint32_t aCount, uint32_t* _retval) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
ShortReadWrapper::IsNonBlocking(bool* _retval) {
  return mBaseStream->IsNonBlocking(_retval);
}

}  // namespace

TEST(ConverterStreamShortRead, ShortRead)
{
  uint8_t bytes[] = {0xd8, 0x35, 0xdc, 0x20};
  nsCOMPtr<nsIInputStream> baseStream;
  ASSERT_TRUE(NS_SUCCEEDED(NS_NewByteInputStream(getter_AddRefs(baseStream),
                                                 AsChars(mozilla::Span(bytes)),
                                                 NS_ASSIGNMENT_COPY)));

  static const uint32_t kShortReads[] = {1, 2, 1};
  nsCOMPtr<nsIInputStream> shortStream =
      new ShortReadWrapper(kShortReads, baseStream);

  RefPtr<nsConverterInputStream> unicharStream = new nsConverterInputStream();
  ASSERT_TRUE(NS_SUCCEEDED(
      unicharStream->Init(shortStream, "UTF-16BE", 4096,
                          nsIConverterInputStream::ERRORS_ARE_FATAL)));

  uint32_t read;
  nsAutoString result;
  ASSERT_TRUE(
      NS_SUCCEEDED(unicharStream->ReadString(UINT32_MAX, result, &read)));

  ASSERT_EQ(read, 2u);
  ASSERT_TRUE(result == u"\u{1d420}");
}

intl/uconv/tests/gtest/moz.build

deleted100644 → 0
+0 −11
Original line number Diff line number Diff line
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.

UNIFIED_SOURCES += [
    "TestShortRead.cpp",
]

FINAL_LIBRARY = "xul-gtest"
+0 −4
Original line number Diff line number Diff line
@@ -4,10 +4,6 @@
# 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/.

TEST_DIRS += [
    "gtest",
]

XPCSHELL_TESTS_MANIFESTS += ["unit/xpcshell.ini"]

MOCHITEST_MANIFESTS += ["mochitest.ini"]
+4 −4
Original line number Diff line number Diff line
@@ -75,14 +75,14 @@ const test = [
  // 10: Lone high surrogate at the end of the input
  [
    "%D8%35%",
    //    expected: one replacement char
    "\uFFFD",
    //    expected: nothing
    "",
  ],
  // 11: Half code unit at the end of the input
  [
    "%D8",
    //    expected: one replacement char
    "\uFFFD",
    //    expected: nothing
    "",
  ],
];

Loading