Bug 1653659 - Part 1: Retrofit hunspell with RLBox for sandboxing r=tjr

Differential Revision: https://phabricator.services.mozilla.com/D84007
This commit is contained in:
Deian Stefan 2021-01-14 20:12:16 +00:00
parent 615c7cc3b1
commit 523d862fa2
20 changed files with 869 additions and 346 deletions

View File

@ -0,0 +1,156 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "mozilla/Assertions.h"
#include "RLBoxHunspell.h"
#include "mozHunspellRLBoxGlue.h"
#include "mozHunspellRLBoxHost.h"
using namespace rlbox;
using namespace mozilla;
// Helper function for allocating and copying nsAutoCString into sandbox
static tainted_hunspell<char*> allocStrInSandbox(
rlbox_sandbox_hunspell& aSandbox, const nsAutoCString& str) {
size_t size = str.Length() + 1;
tainted_hunspell<char*> t_str = aSandbox.malloc_in_sandbox<char>(size);
MOZ_RELEASE_ASSERT(t_str);
rlbox::memcpy(aSandbox, t_str, str.get(), size);
return t_str;
}
// Helper function for allocating and copying std::string into sandbox
static tainted_hunspell<char*> allocStrInSandbox(
rlbox_sandbox_hunspell& aSandbox, const std::string& str) {
size_t size = str.size() + 1;
tainted_hunspell<char*> t_str = aSandbox.malloc_in_sandbox<char>(size);
MOZ_RELEASE_ASSERT(t_str);
rlbox::memcpy(aSandbox, t_str, str.c_str(), size);
return t_str;
}
RLBoxHunspell::RLBoxHunspell(const nsAutoCString& affpath,
const nsAutoCString& dpath)
: mHandle(nullptr) {
mSandbox.create_sandbox();
// Add the aff and dict files to allow list
mozHunspellCallbacks::AllowFile(affpath);
mozHunspellCallbacks::AllowFile(dpath);
// Register callbacks
mCreateFilemgr =
mSandbox.register_callback(mozHunspellCallbacks::CreateFilemgr);
mGetLine = mSandbox.register_callback(mozHunspellCallbacks::GetLine);
mGetLineNum = mSandbox.register_callback(mozHunspellCallbacks::GetLineNum);
mDestructFilemgr =
mSandbox.register_callback(mozHunspellCallbacks::DestructFilemgr);
mHunspellToUpperCase =
mSandbox.register_callback(mozHunspellCallbacks::ToUpperCase);
mHunspellToLowerCase =
mSandbox.register_callback(mozHunspellCallbacks::ToLowerCase);
mHunspellGetCurrentCS =
mSandbox.register_callback(mozHunspellCallbacks::GetCurrentCS);
mSandbox.invoke_sandbox_function(RegisterHunspellCallbacks, mCreateFilemgr,
mGetLine, mGetLineNum, mDestructFilemgr,
mHunspellToUpperCase, mHunspellToLowerCase,
mHunspellGetCurrentCS);
// Copy the affpath and dpath into the sandbox
tainted_hunspell<char*> t_affpath = allocStrInSandbox(mSandbox, affpath);
tainted_hunspell<char*> t_dpath = allocStrInSandbox(mSandbox, dpath);
// Create handle
mHandle = mSandbox.invoke_sandbox_function(
Hunspell_create, rlbox::sandbox_const_cast<const char*>(t_affpath),
rlbox::sandbox_const_cast<const char*>(t_dpath));
MOZ_RELEASE_ASSERT(mHandle);
mSandbox.free_in_sandbox(t_dpath);
mSandbox.free_in_sandbox(t_affpath);
// Get dictionary encoding
tainted_hunspell<char*> t_enc =
mSandbox.invoke_sandbox_function(Hunspell_get_dic_encoding, mHandle);
t_enc.copy_and_verify_string([&](std::unique_ptr<char[]> enc) {
size_t len = std::strlen(enc.get());
mDicEncoding = std::string(enc.get(), len);
});
}
RLBoxHunspell::~RLBoxHunspell() {
// Call hunspell's destroy which frees mHandle
mSandbox.invoke_sandbox_function(Hunspell_destroy, mHandle);
mHandle = nullptr;
// Unregister callbacks
mDestructFilemgr.unregister();
mGetLineNum.unregister();
mGetLine.unregister();
mCreateFilemgr.unregister();
mHunspellToUpperCase.unregister();
mHunspellToLowerCase.unregister();
mHunspellGetCurrentCS.unregister();
// Clear any callback data and allow list
mozHunspellCallbacks::Clear();
// Dstroy sandbox
mSandbox.destroy_sandbox();
}
int RLBoxHunspell::spell(const std::string& stdWord) {
// Copy word into the sandbox
tainted_hunspell<char*> t_word = allocStrInSandbox(mSandbox, stdWord);
// Check word
int good = mSandbox
.invoke_sandbox_function(
Hunspell_spell, mHandle,
rlbox::sandbox_const_cast<const char*>(t_word))
.copy_and_verify([](int good) { return good; });
mSandbox.free_in_sandbox(t_word);
return good;
}
const std::string& RLBoxHunspell::get_dict_encoding() const {
return mDicEncoding;
}
std::vector<std::string> RLBoxHunspell::suggest(const std::string& stdWord) {
// Copy word into the sandbox
tainted_hunspell<char*> t_word = allocStrInSandbox(mSandbox, stdWord);
// Allocate suggestion list in the sandbox
tainted_hunspell<char***> t_slst = mSandbox.malloc_in_sandbox<char**>();
*t_slst = nullptr;
// Get suggestions
int nr = mSandbox
.invoke_sandbox_function(
Hunspell_suggest, mHandle, t_slst,
rlbox::sandbox_const_cast<const char*>(t_word))
.copy_and_verify([](int nr) {
MOZ_RELEASE_ASSERT(nr >= 0);
return nr;
});
// Copy suggestions from sandbox
std::vector<std::string> suggestions;
suggestions.reserve(nr);
for (int i = 0; i < nr; i++) {
tainted_hunspell<char*> t_sug = (*t_slst)[i];
MOZ_RELEASE_ASSERT(t_sug);
t_sug.copy_and_verify_string([&](std::unique_ptr<char[]> sug) {
size_t len = std::strlen(sug.get());
suggestions.push_back(std::string(sug.get(), len));
});
}
mSandbox.free_in_sandbox(t_word);
mSandbox.free_in_sandbox(t_slst);
return suggestions;
}

View File

@ -0,0 +1,50 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef EXTENSIONS_SPELLCHECK_HUNSPELL_GLUE_RLBOXHUNSPELL_H_
#define EXTENSIONS_SPELLCHECK_HUNSPELL_GLUE_RLBOXHUNSPELL_H_
#include "RLBoxHunspellTypes.h"
// Load general firefox configuration of RLBox
#include "mozilla/rlbox/rlbox_config.h"
#ifdef MOZ_WASM_SANDBOXING_HUNSPELL
# include "mozilla/rlbox/rlbox_lucet_sandbox.hpp"
#else
// Extra configuration for no-op sandbox
# define RLBOX_USE_STATIC_CALLS() rlbox_noop_sandbox_lookup_symbol
# include "mozilla/rlbox/rlbox_noop_sandbox.hpp"
#endif
#include "mozilla/rlbox/rlbox.hpp"
#include <hunspell.h>
#include "mozHunspellRLBoxGlue.h"
class RLBoxHunspell {
public:
RLBoxHunspell(const nsAutoCString& affpath, const nsAutoCString& dpath);
~RLBoxHunspell();
int spell(const std::string& stdWord);
const std::string& get_dict_encoding() const;
std::vector<std::string> suggest(const std::string& word);
private:
rlbox_sandbox_hunspell mSandbox;
sandbox_callback_hunspell<hunspell_create_filemgr_t*> mCreateFilemgr;
sandbox_callback_hunspell<hunspell_get_line_t*> mGetLine;
sandbox_callback_hunspell<hunspell_get_line_num_t*> mGetLineNum;
sandbox_callback_hunspell<hunspell_destruct_filemgr_t*> mDestructFilemgr;
sandbox_callback_hunspell<hunspell_ToUpperCase_t*> mHunspellToUpperCase;
sandbox_callback_hunspell<hunspell_ToLowerCase_t*> mHunspellToLowerCase;
sandbox_callback_hunspell<hunspell_get_current_cs_t*> mHunspellGetCurrentCS;
tainted_hunspell<Hunhandle*> mHandle;
std::string mDicEncoding;
};
#endif

View File

@ -0,0 +1,45 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef EXTENSIONS_SPELLCHECK_HUNSPELL_GLUE_RLBOXHUNSPELLTYPES_H_
#define EXTENSIONS_SPELLCHECK_HUNSPELL_GLUE_RLBOXHUNSPELLTYPES_H_
#include <stddef.h>
#include "mozilla/rlbox/rlbox_types.hpp"
#include "hunspell_csutil.hxx"
#ifdef MOZ_WASM_SANDBOXING_HUNSPELL
namespace rlbox {
class rlbox_lucet_sandbox;
}
using rlbox_hunspell_sandbox_type = rlbox::rlbox_lucet_sandbox;
#else
using rlbox_hunspell_sandbox_type = rlbox::rlbox_noop_sandbox;
#endif
using rlbox_sandbox_hunspell =
rlbox::rlbox_sandbox<rlbox_hunspell_sandbox_type>;
template <typename T>
using sandbox_callback_hunspell =
rlbox::sandbox_callback<T, rlbox_hunspell_sandbox_type>;
template <typename T>
using tainted_hunspell = rlbox::tainted<T, rlbox_hunspell_sandbox_type>;
template <typename T>
using tainted_opaque_hunspell =
rlbox::tainted_opaque<T, rlbox_hunspell_sandbox_type>;
template <typename T>
using tainted_volatile_hunspell =
rlbox::tainted_volatile<T, rlbox_hunspell_sandbox_type>;
using rlbox::tainted_boolean_hint;
#define sandbox_fields_reflection_hunspell_class_cs_info(f, g, ...) \
f(unsigned char, ccase, FIELD_NORMAL, ##__VA_ARGS__) g() \
f(unsigned char, clower, FIELD_NORMAL, ##__VA_ARGS__) g() \
f(unsigned char, cupper, FIELD_NORMAL, ##__VA_ARGS__) g()
#define sandbox_fields_reflection_hunspell_allClasses(f, ...) \
f(cs_info, hunspell, ##__VA_ARGS__)
#endif

View File

@ -0,0 +1,158 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* Hunspell is based on MySpell which is Copyright (C) 2002 Kevin Hendricks.
*
* Contributor(s): David Einstein, Davide Prina, Giuseppe Modugno,
* Gianluca Turconi, Simon Brouwer, Noll János, Bíró Árpád,
* Goldman Eleonóra, Sarlós Tamás, Bencsáth Boldizsár, Halácsy Péter,
* Dvornik László, Gefferth András, Nagy Viktor, Varga Dániel, Chris Halls,
* Rene Engelhard, Bram Moolenaar, Dafydd Jones, Harri Pitkänen
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* Copyright 2002 Kevin B. Hendricks, Stratford, Ontario, Canada
* And Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. All modifications to the source code must be clearly marked as
* such. Binary redistributions based on modified source code
* must be clearly marked as modified versions in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY KEVIN B. HENDRICKS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* KEVIN B. HENDRICKS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "hunspell_csutil.hxx"
#include "mozilla/Encoding.h"
/* This is a copy of get_current_cs from the hunspell csutil.cxx file.
*/
struct cs_info* hunspell_get_current_cs(const std::string& es) {
struct cs_info* ccs = new cs_info[256];
// Initialze the array with dummy data so that we wouldn't need
// to return null in case of failures.
for (int i = 0; i <= 0xff; ++i) {
ccs[i].ccase = false;
ccs[i].clower = i;
ccs[i].cupper = i;
}
auto encoding = Encoding::ForLabelNoReplacement(es);
if (!encoding) {
return ccs;
}
auto encoder = encoding->NewEncoder();
auto decoder = encoding->NewDecoderWithoutBOMHandling();
for (unsigned int i = 0; i <= 0xff; ++i) {
bool success = false;
// We want to find the upper/lowercase equivalents of each byte
// in this 1-byte character encoding. Call our encoding/decoding
// APIs separately for each byte since they may reject some of the
// bytes, and we want to handle errors separately for each byte.
uint8_t lower, upper;
do {
if (i == 0) break;
uint8_t source = uint8_t(i);
char16_t uni[2];
char16_t uniCased;
uint8_t destination[4];
auto src1 = Span(&source, 1);
auto dst1 = Span(uni);
auto src2 = Span(&uniCased, 1);
auto dst2 = Span(destination);
uint32_t result;
size_t read;
size_t written;
Tie(result, read, written) =
decoder->DecodeToUTF16WithoutReplacement(src1, dst1, true);
if (result != kInputEmpty || read != 1 || written != 1) {
break;
}
uniCased = ToLowerCase(uni[0]);
Tie(result, read, written) =
encoder->EncodeFromUTF16WithoutReplacement(src2, dst2, true);
if (result != kInputEmpty || read != 1 || written != 1) {
break;
}
lower = destination[0];
uniCased = ToUpperCase(uni[0]);
Tie(result, read, written) =
encoder->EncodeFromUTF16WithoutReplacement(src2, dst2, true);
if (result != kInputEmpty || read != 1 || written != 1) {
break;
}
upper = destination[0];
success = true;
} while (0);
encoding->NewEncoderInto(*encoder);
encoding->NewDecoderWithoutBOMHandlingInto(*decoder);
if (success) {
ccs[i].cupper = upper;
ccs[i].clower = lower;
} else {
ccs[i].cupper = i;
ccs[i].clower = i;
}
if (ccs[i].clower != (unsigned char)i)
ccs[i].ccase = true;
else
ccs[i].ccase = false;
}
return ccs;
}

View File

@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* Hunspell is based on MySpell which is Copyright (C) 2002 Kevin Hendricks.
*
* Contributor(s): David Einstein, Davide Prina, Giuseppe Modugno,
* Gianluca Turconi, Simon Brouwer, Noll János, Bíró Árpád,
* Goldman Eleonóra, Sarlós Tamás, Bencsáth Boldizsár, Halácsy Péter,
* Dvornik László, Gefferth András, Nagy Viktor, Varga Dániel, Chris Halls,
* Rene Engelhard, Bram Moolenaar, Dafydd Jones, Harri Pitkänen
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* Copyright 2002 Kevin B. Hendricks, Stratford, Ontario, Canada
* And Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. All modifications to the source code must be clearly marked as
* such. Binary redistributions based on modified source code
* must be clearly marked as modified versions in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY KEVIN B. HENDRICKS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* KEVIN B. HENDRICKS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef EXTENSIONS_SPELLCHECK_HUNSPELL_GLUE_HUNSPELL_CSUTIL_H_
#define EXTENSIONS_SPELLCHECK_HUNSPELL_GLUE_HUNSPELL_CSUTIL_H_
/* We need get_current_cs from hunspell's csutil to live outside the RLBox
* sandbox (since it relies on a Gecko encoding bits) and then expose it to the
* sandboxed hunspell.
*/
struct cs_info {
unsigned char ccase;
unsigned char clower;
unsigned char cupper;
};
struct cs_info* hunspell_get_current_cs(const std::string& es);
#endif

View File

@ -5,10 +5,12 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
"hunspell_csutil.cxx",
"mozHunspell.cpp",
"mozHunspellFileMgrHost.cpp",
"mozHunspellRLBoxHost.cpp",
"RemoteSpellCheckEngineChild.cpp",
"RemoteSpellCheckEngineParent.cpp",
"RLBoxHunspell.cpp",
]
DEFINES["HUNSPELL_STATIC"] = True

View File

@ -58,8 +58,6 @@
******* END LICENSE BLOCK *******/
#include "mozHunspell.h"
#include "mozHunspellFileMgrGlue.h"
#include "mozHunspellFileMgrHost.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#include "nsIObserverService.h"
@ -188,10 +186,7 @@ mozHunspell::SetDictionary(const nsACString& aDictionary) {
mDictionary = dict;
mAffixFileName = affFileName;
RegisterHunspellCallbacks(
mozHunspellCallbacks::CreateFilemgr, mozHunspellCallbacks::GetLine,
mozHunspellCallbacks::GetLineNum, mozHunspellCallbacks::DestructFilemgr);
mHunspell = new Hunspell(affFileName.get(), dictFileName.get());
mHunspell = new RLBoxHunspell(affFileName, dictFileName);
if (!mHunspell) return NS_ERROR_OUT_OF_MEMORY;
auto encoding =

View File

@ -60,7 +60,7 @@
#ifndef mozHunspell_h__
#define mozHunspell_h__
#include <hunspell.hxx>
#include "RLBoxHunspell.h"
#include "mozISpellCheckingEngine.h"
#include "mozIPersonalDictionary.h"
#include "nsString.h"
@ -123,7 +123,7 @@ class mozHunspell final : public mozISpellCheckingEngine,
nsCOMArray<nsIFile> mDynamicDirectories;
nsInterfaceHashtable<nsStringHashKey, nsIURI> mDynamicDictionaries;
Hunspell* mHunspell;
RLBoxHunspell* mHunspell;
};
#endif

View File

@ -1,139 +0,0 @@
/* -*- 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 <limits>
#include "mozHunspellFileMgrHost.h"
#include "mozilla/DebugOnly.h"
#include "nsContentUtils.h"
#include "nsIChannel.h"
#include "nsILoadInfo.h"
#include "nsNetUtil.h"
using namespace mozilla;
mozHunspellFileMgrHost::mozHunspellFileMgrHost(const char* aFilename,
const char* aKey) {
DebugOnly<Result<Ok, nsresult>> result = Open(nsDependentCString(aFilename));
NS_WARNING_ASSERTION(result.value.isOk(), "Failed to open Hunspell file");
}
Result<Ok, nsresult> mozHunspellFileMgrHost::Open(const nsACString& aPath) {
nsCOMPtr<nsIURI> uri;
MOZ_TRY(NS_NewURI(getter_AddRefs(uri), aPath));
nsCOMPtr<nsIChannel> channel;
MOZ_TRY(NS_NewChannel(
getter_AddRefs(channel), uri, nsContentUtils::GetSystemPrincipal(),
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_INHERITS_SEC_CONTEXT,
nsIContentPolicy::TYPE_OTHER));
MOZ_TRY(channel->Open(getter_AddRefs(mStream)));
return Ok();
}
Result<Ok, nsresult> mozHunspellFileMgrHost::ReadLine(nsACString& aLine) {
if (!mStream) {
return Err(NS_ERROR_NOT_INITIALIZED);
}
bool ok;
MOZ_TRY(NS_ReadLine(mStream.get(), &mLineBuffer, aLine, &ok));
if (!ok) {
mStream = nullptr;
}
mLineNum++;
return Ok();
}
bool mozHunspellFileMgrHost::GetLine(std::string& aResult) {
nsAutoCString line;
auto res = ReadLine(line);
if (res.isErr()) {
return false;
}
aResult.assign(line.BeginReading(), line.Length());
return true;
}
/* static */
uint32_t mozHunspellCallbacks::sCurrentFreshId = 0;
/* static */
mozilla::detail::StaticRWLock mozHunspellCallbacks::sFileMgrMapLock;
/* static */
std::map<uint32_t, std::unique_ptr<mozHunspellFileMgrHost>>
mozHunspellCallbacks::sFileMgrMap;
/* static */
uint32_t mozHunspellCallbacks::CreateFilemgr(const char* aFilename,
const char* aKey) {
mozilla::detail::StaticAutoWriteLock lock(sFileMgrMapLock);
uint32_t freshId = GetFreshId();
sFileMgrMap[freshId] = std::unique_ptr<mozHunspellFileMgrHost>(
new mozHunspellFileMgrHost(aFilename, aKey));
return freshId;
}
/* static */
uint32_t mozHunspellCallbacks::GetFreshId() {
// i is uint64_t to prevent overflow during loop increment which would cause
// an infinite loop
for (uint64_t i = sCurrentFreshId; i < std::numeric_limits<uint32_t>::max();
i++) {
auto it = sFileMgrMap.find(i);
if (it == sFileMgrMap.end()) {
// set sCurrentFreshId to the next (possibly) available id
sCurrentFreshId = i + 1;
return static_cast<uint32_t>(i);
}
}
MOZ_CRASH("Ran out of unique file ids for hunspell dictionaries");
}
/* static */
mozHunspellFileMgrHost& mozHunspellCallbacks::GetMozHunspellFileMgrHost(
uint32_t aFd) {
mozilla::detail::StaticAutoReadLock lock(sFileMgrMapLock);
auto iter = sFileMgrMap.find(aFd);
MOZ_RELEASE_ASSERT(iter != sFileMgrMap.end());
return *(iter->second.get());
}
/* static */
bool mozHunspellCallbacks::GetLine(uint32_t aFd, char** aLinePtr) {
mozHunspellFileMgrHost& inst =
mozHunspellCallbacks::GetMozHunspellFileMgrHost(aFd);
std::string line;
bool ok = inst.GetLine(line);
if (ok) {
*aLinePtr = static_cast<char*>(malloc(line.size() + 1));
strcpy(*aLinePtr, line.c_str());
} else {
*aLinePtr = nullptr;
}
return ok;
}
/* static */
int mozHunspellCallbacks::GetLineNum(uint32_t aFd) {
mozHunspellFileMgrHost& inst =
mozHunspellCallbacks::GetMozHunspellFileMgrHost(aFd);
int num = inst.GetLineNum();
return num;
}
/* static */
void mozHunspellCallbacks::DestructFilemgr(uint32_t aFd) {
mozilla::detail::StaticAutoWriteLock lock(sFileMgrMapLock);
auto iter = sFileMgrMap.find(aFd);
if (iter != sFileMgrMap.end()) {
sFileMgrMap.erase(iter);
}
}

View File

@ -1,83 +0,0 @@
/* -*- 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/. */
#ifndef mozHunspellFileMgrHost_h
#define mozHunspellFileMgrHost_h
#include <map>
#include <memory>
#include <mutex>
#include <stdint.h>
#include <string>
#include "mozilla/Result.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/RWLock.h"
#include "nsIInputStream.h"
#include "nsReadLine.h"
namespace mozilla {
class mozHunspellFileMgrHost final {
public:
/**
* aFilename must be a local file/jar URI for the file to load.
*
* aKey is the decription key for encrypted Hunzip files, and is
* unsupported. The argument is there solely for compatibility.
*/
explicit mozHunspellFileMgrHost(const char* aFilename,
const char* aKey = nullptr);
~mozHunspellFileMgrHost() = default;
bool GetLine(std::string& aResult);
int GetLineNum() const { return mLineNum; }
private:
mozilla::Result<mozilla::Ok, nsresult> Open(const nsACString& aPath);
mozilla::Result<mozilla::Ok, nsresult> ReadLine(nsACString& aLine);
int mLineNum = 0;
nsCOMPtr<nsIInputStream> mStream;
nsLineBuffer<char> mLineBuffer;
};
class mozHunspellCallbacks {
public:
// APIs invoked by the sandboxed hunspell file manager
static uint32_t CreateFilemgr(const char* aFilename, const char* aKey);
static bool GetLine(uint32_t aFd, char** aLinePtr);
static int GetLineNum(uint32_t aFd);
static void DestructFilemgr(uint32_t aFd);
private:
/**
* sFileMgrMap holds a map between unique uint32_t
* integers and mozHunspellFileMgrHost instances
*/
static std::map<uint32_t, std::unique_ptr<mozHunspellFileMgrHost>>
sFileMgrMap;
/**
* Reader-writer lock for the sFileMgrMap
*/
static mozilla::detail::StaticRWLock sFileMgrMapLock;
/**
* Tracks the next possibly unused id for sFileMgrMap
*/
static uint32_t sCurrentFreshId;
/**
* Returns an unused id for sFileMgrMap
*/
static uint32_t GetFreshId();
/**
* Returns the mozHunspellFileMgrHost for the given uint32_t id
*/
static mozHunspellFileMgrHost& GetMozHunspellFileMgrHost(uint32_t aFd);
};
} // namespace mozilla
#endif

View File

@ -4,8 +4,8 @@
* 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/. */
#ifndef mozHunspellFileMgrGlue_h
#define mozHunspellFileMgrGlue_h
#ifndef mozHunspellRLBoxGlue_h
#define mozHunspellRLBoxGlue_h
#include <stdint.h>
@ -13,22 +13,30 @@
extern "C" {
#endif
typedef uint32_t(hunspell_create_filemgr_t)(const char* aFilename,
const char* aKey);
typedef uint32_t(hunspell_create_filemgr_t)(const char* aFilename);
typedef bool(hunspell_get_line_t)(uint32_t aFd, char** aLinePtr);
typedef int(hunspell_get_line_num_t)(uint32_t aFd);
typedef void(hunspell_destruct_filemgr_t)(uint32_t aFd);
typedef uint32_t(hunspell_ToUpperCase_t)(uint32_t aChar);
typedef uint32_t(hunspell_ToLowerCase_t)(uint32_t aChar);
typedef struct cs_info*(hunspell_get_current_cs_t)(const char* es);
void RegisterHunspellCallbacks(
hunspell_create_filemgr_t* aHunspellCreateFilemgr,
hunspell_get_line_t* aHunspellGetLine,
hunspell_get_line_num_t* aHunspellGetLine_num,
hunspell_destruct_filemgr_t* aHunspellDestructFilemgr);
hunspell_destruct_filemgr_t* aHunspellDestructFilemgr,
hunspell_ToUpperCase_t* aHunspellToUpperCase,
hunspell_ToLowerCase_t* aHunspellToLowerCase,
hunspell_get_current_cs_t* aHunspellGetCurrentCS);
extern hunspell_create_filemgr_t* moz_glue_hunspell_create_filemgr;
extern hunspell_get_line_t* moz_glue_hunspell_get_line;
extern hunspell_get_line_num_t* moz_glue_hunspell_get_line_num;
extern hunspell_destruct_filemgr_t* moz_glue_hunspell_destruct_filemgr;
extern hunspell_ToUpperCase_t* moz_hunspell_ToUpperCase;
extern hunspell_ToLowerCase_t* moz_hunspell_ToLowerCase;
extern hunspell_get_current_cs_t* moz_hunspell_GetCurrentCS;
#if defined(__cplusplus)
}

View File

@ -0,0 +1,213 @@
/* -*- 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 <limits>
#include "mozHunspellRLBoxHost.h"
#include "mozilla/DebugOnly.h"
#include "nsContentUtils.h"
#include "nsIChannel.h"
#include "nsILoadInfo.h"
#include "nsNetUtil.h"
#include "nsUnicharUtils.h"
#include "hunspell_csutil.hxx"
using namespace mozilla;
mozHunspellFileMgrHost::mozHunspellFileMgrHost(const nsCString& aFilename) {
DebugOnly<Result<Ok, nsresult>> result = Open(aFilename);
NS_WARNING_ASSERTION(result.value.isOk(), "Failed to open Hunspell file");
}
Result<Ok, nsresult> mozHunspellFileMgrHost::Open(const nsCString& aPath) {
nsCOMPtr<nsIURI> uri;
MOZ_TRY(NS_NewURI(getter_AddRefs(uri), aPath));
nsCOMPtr<nsIChannel> channel;
MOZ_TRY(NS_NewChannel(
getter_AddRefs(channel), uri, nsContentUtils::GetSystemPrincipal(),
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_INHERITS_SEC_CONTEXT,
nsIContentPolicy::TYPE_OTHER));
MOZ_TRY(channel->Open(getter_AddRefs(mStream)));
return Ok();
}
Result<Ok, nsresult> mozHunspellFileMgrHost::ReadLine(nsCString& aLine) {
if (!mStream) {
return Err(NS_ERROR_NOT_INITIALIZED);
}
bool ok;
MOZ_TRY(NS_ReadLine(mStream.get(), &mLineBuffer, aLine, &ok));
if (!ok) {
mStream = nullptr;
}
mLineNum++;
return Ok();
}
bool mozHunspellFileMgrHost::GetLine(std::string& aResult) {
nsAutoCString line;
auto res = ReadLine(line);
if (res.isErr()) {
return false;
}
aResult.assign(line.BeginReading(), line.Length());
return true;
}
/* static */
uint32_t mozHunspellCallbacks::sCurrentFreshId = 0;
/* static */
mozilla::detail::StaticRWLock mozHunspellCallbacks::sFileMgrMapLock;
/* static */
std::map<uint32_t, std::unique_ptr<mozHunspellFileMgrHost>>
mozHunspellCallbacks::sFileMgrMap;
/* static */
std::set<nsCString> mozHunspellCallbacks::sFileMgrAllowList;
/* static */
void mozHunspellCallbacks::AllowFile(const nsCString& aFilename) {
mozilla::detail::StaticAutoWriteLock lock(sFileMgrMapLock);
sFileMgrAllowList.insert(aFilename);
}
/* static */
void mozHunspellCallbacks::Clear() {
mozilla::detail::StaticAutoWriteLock lock(sFileMgrMapLock);
sCurrentFreshId = 0;
sFileMgrMap.clear();
sFileMgrAllowList.clear();
}
/* static */
tainted_hunspell<uint32_t> mozHunspellCallbacks::CreateFilemgr(
rlbox_sandbox_hunspell& aSandbox,
tainted_hunspell<const char*> t_aFilename) {
mozilla::detail::StaticAutoWriteLock lock(sFileMgrMapLock);
return t_aFilename.copy_and_verify_string(
[&](std::unique_ptr<char[]> aFilename) {
nsCString cFilename = nsDependentCString(aFilename.get());
// Ensure that the filename is in the allowlist
auto it = sFileMgrAllowList.find(cFilename);
MOZ_RELEASE_ASSERT(it != sFileMgrAllowList.end());
// Get new id
uint32_t freshId = GetFreshId();
// Save mapping of id to file manager
sFileMgrMap[freshId] = std::unique_ptr<mozHunspellFileMgrHost>(
new mozHunspellFileMgrHost(cFilename));
return freshId;
});
}
/* static */
uint32_t mozHunspellCallbacks::GetFreshId() {
// i is uint64_t to prevent overflow during loop increment which would cause
// an infinite loop
for (uint64_t i = sCurrentFreshId; i < std::numeric_limits<uint32_t>::max();
i++) {
auto it = sFileMgrMap.find(i);
if (it == sFileMgrMap.end()) {
// set sCurrentFreshId to the next (possibly) available id
sCurrentFreshId = i + 1;
return static_cast<uint32_t>(i);
}
}
MOZ_CRASH("Ran out of unique file ids for hunspell dictionaries");
}
/* static */
mozHunspellFileMgrHost& mozHunspellCallbacks::GetMozHunspellFileMgrHost(
tainted_hunspell<uint32_t> t_aFd) {
mozilla::detail::StaticAutoReadLock lock(sFileMgrMapLock);
uint32_t aFd = t_aFd.copy_and_verify([](uint32_t aFd) { return aFd; });
auto iter = sFileMgrMap.find(aFd);
MOZ_RELEASE_ASSERT(iter != sFileMgrMap.end());
return *(iter->second.get());
}
/* static */
tainted_hunspell<bool> mozHunspellCallbacks::GetLine(
rlbox_sandbox_hunspell& aSandbox, tainted_hunspell<uint32_t> t_aFd,
tainted_hunspell<char**> t_aLinePtr) {
mozHunspellFileMgrHost& inst =
mozHunspellCallbacks::GetMozHunspellFileMgrHost(t_aFd);
std::string line;
bool ok = inst.GetLine(line);
if (ok) {
// copy the line into the sandbox
size_t size = line.size() + 1;
tainted_hunspell<char*> t_line = aSandbox.malloc_in_sandbox<char>(size);
MOZ_RELEASE_ASSERT(t_line);
rlbox::memcpy(aSandbox, t_line, line.c_str(), size);
*t_aLinePtr = t_line;
} else {
*t_aLinePtr = nullptr;
}
return ok;
}
/* static */
tainted_hunspell<int> mozHunspellCallbacks::GetLineNum(
rlbox_sandbox_hunspell& aSandbox, tainted_hunspell<uint32_t> t_aFd) {
mozHunspellFileMgrHost& inst =
mozHunspellCallbacks::GetMozHunspellFileMgrHost(t_aFd);
int num = inst.GetLineNum();
return num;
}
/* static */
void mozHunspellCallbacks::DestructFilemgr(rlbox_sandbox_hunspell& aSandbox,
tainted_hunspell<uint32_t> t_aFd) {
mozilla::detail::StaticAutoWriteLock lock(sFileMgrMapLock);
uint32_t aFd = t_aFd.copy_and_verify([](uint32_t aFd) { return aFd; });
auto iter = sFileMgrMap.find(aFd);
if (iter != sFileMgrMap.end()) {
sFileMgrMap.erase(iter);
}
}
// Callbacks for using Firefox's encoding instead of hunspell's
/* static */
tainted_hunspell<uint32_t> mozHunspellCallbacks::ToUpperCase(
rlbox_sandbox_hunspell& aSandbox, tainted_hunspell<uint32_t> t_aChar) {
uint32_t aChar =
t_aChar.copy_and_verify([](uint32_t aChar) { return aChar; });
return ::ToUpperCase(aChar);
}
/* static */
tainted_hunspell<uint32_t> mozHunspellCallbacks::ToLowerCase(
rlbox_sandbox_hunspell& aSandbox, tainted_hunspell<uint32_t> t_aChar) {
uint32_t aChar =
t_aChar.copy_and_verify([](uint32_t aChar) { return aChar; });
return ::ToLowerCase(aChar);
}
/* static */ tainted_hunspell<struct cs_info*>
mozHunspellCallbacks::GetCurrentCS(rlbox_sandbox_hunspell& aSandbox,
tainted_hunspell<const char*> t_es) {
tainted_hunspell<struct cs_info*> t_ccs =
aSandbox.malloc_in_sandbox<struct cs_info>(256);
MOZ_RELEASE_ASSERT(t_ccs);
return t_es.copy_and_verify_string([&](std::unique_ptr<char[]> es) {
struct cs_info* ccs = hunspell_get_current_cs(es.get());
rlbox::memcpy(aSandbox, t_ccs, ccs, sizeof(struct cs_info) * 256);
delete[] ccs;
return t_ccs;
});
}

View File

@ -0,0 +1,117 @@
/* -*- 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/. */
#ifndef mozHunspellRLBoxHost_h
#define mozHunspellRLBoxHost_h
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <stdint.h>
#include <string>
#include "RLBoxHunspell.h"
#include "mozilla/Result.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/RWLock.h"
#include "nsIInputStream.h"
#include "nsReadLine.h"
namespace mozilla {
class mozHunspellFileMgrHost final {
public:
/**
* aFilename must be a local file/jar URI for the file to load.
*/
explicit mozHunspellFileMgrHost(const nsCString& aFilename);
~mozHunspellFileMgrHost() = default;
bool GetLine(std::string& aResult);
int GetLineNum() const { return mLineNum; }
private:
mozilla::Result<mozilla::Ok, nsresult> Open(const nsCString& aPath);
mozilla::Result<mozilla::Ok, nsresult> ReadLine(nsCString& aLine);
int mLineNum = 0;
nsCOMPtr<nsIInputStream> mStream;
nsLineBuffer<char> mLineBuffer;
};
class mozHunspellCallbacks {
public:
// APIs invoked by the sandboxed hunspell file manager
static tainted_hunspell<uint32_t> CreateFilemgr(
rlbox_sandbox_hunspell& aSandbox,
tainted_hunspell<const char*> t_aFilename);
static tainted_hunspell<bool> GetLine(rlbox_sandbox_hunspell& aSandbox,
tainted_hunspell<uint32_t> t_aFd,
tainted_hunspell<char**> t_aLinePtr);
static tainted_hunspell<int> GetLineNum(rlbox_sandbox_hunspell& aSandbox,
tainted_hunspell<uint32_t> t_aFd);
static void DestructFilemgr(rlbox_sandbox_hunspell& aSandbox,
tainted_hunspell<uint32_t> t_aFd);
// APIs necessary for hunspell UTF encoding
static tainted_hunspell<uint32_t> ToUpperCase(
rlbox_sandbox_hunspell& aSandbox, tainted_hunspell<uint32_t> t_aChar);
static tainted_hunspell<uint32_t> ToLowerCase(
rlbox_sandbox_hunspell& aSandbox, tainted_hunspell<uint32_t> t_aChar);
static tainted_hunspell<struct cs_info*> GetCurrentCS(
rlbox_sandbox_hunspell& aSandbox, tainted_hunspell<const char*> t_es);
protected:
// API called by RLBox
/**
* Add filename to allow list.
*/
static void AllowFile(const nsCString& aFilename);
friend RLBoxHunspell::RLBoxHunspell(const nsAutoCString& affpath,
const nsAutoCString& dpath);
/**
* Clear allow list and map of hunspell file managers.
*/
static void Clear();
friend RLBoxHunspell::~RLBoxHunspell();
private:
/**
* sFileMgrMap holds a map between unique uint32_t
* integers and mozHunspellFileMgrHost instances
*/
static std::map<uint32_t, std::unique_ptr<mozHunspellFileMgrHost>>
sFileMgrMap;
/**
* sFileMgrAllowList contains the filenames of the dictionary files hunspell
* is allowed to open
*/
static std::set<nsCString> sFileMgrAllowList;
/**
* Reader-writer lock for the sFileMgrMap
*/
static mozilla::detail::StaticRWLock sFileMgrMapLock;
/**
* Tracks the next possibly unused id for sFileMgrMap
*/
static uint32_t sCurrentFreshId;
/**
* Returns an unused id for sFileMgrMap
*/
static uint32_t GetFreshId();
/**
* Returns the mozHunspellFileMgrHost for the given uint32_t id
*/
static mozHunspellFileMgrHost& GetMozHunspellFileMgrHost(
tainted_hunspell<uint32_t> t_aFd);
};
} // namespace mozilla
#endif

View File

@ -4,11 +4,12 @@
* 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 "mozHunspellFileMgrSandbox.h"
#include "mozHunspellFileMgrGlue.h"
#include "mozHunspellRLBoxSandbox.h"
#include "mozHunspellRLBoxGlue.h"
FileMgr::FileMgr(const char* aFilename, const char* aKey) : mFd(0) {
mFd = moz_glue_hunspell_create_filemgr(aFilename, aKey);
// The key is not used in firefox
mFd = moz_glue_hunspell_create_filemgr(aFilename);
}
bool FileMgr::getline(std::string& aResult) {
@ -31,14 +32,23 @@ hunspell_create_filemgr_t* moz_glue_hunspell_create_filemgr = nullptr;
hunspell_get_line_t* moz_glue_hunspell_get_line = nullptr;
hunspell_get_line_num_t* moz_glue_hunspell_get_line_num = nullptr;
hunspell_destruct_filemgr_t* moz_glue_hunspell_destruct_filemgr = nullptr;
hunspell_ToUpperCase_t* moz_hunspell_ToUpperCase = nullptr;
hunspell_ToLowerCase_t* moz_hunspell_ToLowerCase = nullptr;
hunspell_get_current_cs_t* moz_hunspell_GetCurrentCS = nullptr;
void RegisterHunspellCallbacks(
hunspell_create_filemgr_t* aHunspellCreateFilemgr,
hunspell_get_line_t* aHunspellGetLine,
hunspell_get_line_num_t* aHunspellGetLine_num,
hunspell_destruct_filemgr_t* aHunspellDestructFilemgr) {
hunspell_destruct_filemgr_t* aHunspellDestructFilemgr,
hunspell_ToUpperCase_t* aHunspellToUpperCase,
hunspell_ToLowerCase_t* aHunspellToLowerCase,
hunspell_get_current_cs_t* aHunspellGetCurrentCS) {
moz_glue_hunspell_create_filemgr = aHunspellCreateFilemgr;
moz_glue_hunspell_get_line = aHunspellGetLine;
moz_glue_hunspell_get_line_num = aHunspellGetLine_num;
moz_glue_hunspell_destruct_filemgr = aHunspellDestructFilemgr;
moz_hunspell_ToUpperCase = aHunspellToUpperCase;
moz_hunspell_ToLowerCase = aHunspellToLowerCase;
moz_hunspell_GetCurrentCS = aHunspellGetCurrentCS;
}

View File

@ -4,17 +4,12 @@
* 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/. */
#ifndef mozHunspellFileMgrSandbox_h
#define mozHunspellFileMgrSandbox_h
#ifndef mozHunspellRLBoxSandbox_h
#define mozHunspellRLBoxSandbox_h
#include <string>
#include <stdint.h>
#include "mozilla/Result.h"
#include "mozilla/ResultExtensions.h"
#include "nsIInputStream.h"
#include "nsReadLine.h"
// Note: This class name and lack of namespacing terrible, but are necessary
// for Hunspell compatibility.
class FileMgr final {
@ -38,4 +33,4 @@ class FileMgr final {
uint32_t mFd;
};
#endif // mozHunspellFileMgrSandbox_h
#endif // mozHunspellRLBoxSandbox_h

View File

@ -154,7 +154,7 @@ diff --git a/extensions/spellcheck/hunspell/src/filemgr.hxx b/extensions/spellch
- private:
- FileMgr(const FileMgr&);
- FileMgr& operator=(const FileMgr&);
+#include "mozHunspellFileMgrSandbox.h"
+#include "mozHunspellRLBoxSandbox.h"
- protected:
- std::ifstream fin;

View File

@ -95,11 +95,7 @@
#endif
#ifdef MOZILLA_CLIENT
#include "nsCOMPtr.h"
#include "nsUnicharUtils.h"
#include "mozilla/Encoding.h"
using namespace mozilla;
#include "mozHunspellRLBoxGlue.h"
#endif
struct unicode_info2 {
@ -2282,91 +2278,8 @@ struct cs_info* get_current_cs(const std::string& es) {
return ccs;
}
#else
// XXX This function was rewritten for mozilla. Instead of storing the
// conversion tables static in this file, create them when needed
// with help the mozilla backend.
struct cs_info* get_current_cs(const std::string& es) {
struct cs_info* ccs = new cs_info[256];
// Initialze the array with dummy data so that we wouldn't need
// to return null in case of failures.
for (int i = 0; i <= 0xff; ++i) {
ccs[i].ccase = false;
ccs[i].clower = i;
ccs[i].cupper = i;
}
auto encoding = Encoding::ForLabelNoReplacement(es);
if (!encoding) {
return ccs;
}
auto encoder = encoding->NewEncoder();
auto decoder = encoding->NewDecoderWithoutBOMHandling();
for (unsigned int i = 0; i <= 0xff; ++i) {
bool success = false;
// We want to find the upper/lowercase equivalents of each byte
// in this 1-byte character encoding. Call our encoding/decoding
// APIs separately for each byte since they may reject some of the
// bytes, and we want to handle errors separately for each byte.
uint8_t lower, upper;
do {
if (i == 0)
break;
uint8_t source = uint8_t(i);
char16_t uni[2];
char16_t uniCased;
uint8_t destination[4];
auto src1 = Span(&source, 1);
auto dst1 = Span(uni);
auto src2 = Span(&uniCased, 1);
auto dst2 = Span(destination);
uint32_t result;
size_t read;
size_t written;
Tie(result, read, written) =
decoder->DecodeToUTF16WithoutReplacement(src1, dst1, true);
if (result != kInputEmpty || read != 1 || written != 1) {
break;
}
uniCased = ToLowerCase(uni[0]);
Tie(result, read, written) =
encoder->EncodeFromUTF16WithoutReplacement(src2, dst2, true);
if (result != kInputEmpty || read != 1 || written != 1) {
break;
}
lower = destination[0];
uniCased = ToUpperCase(uni[0]);
Tie(result, read, written) =
encoder->EncodeFromUTF16WithoutReplacement(src2, dst2, true);
if (result != kInputEmpty || read != 1 || written != 1) {
break;
}
upper = destination[0];
success = true;
} while (0);
encoding->NewEncoderInto(*encoder);
encoding->NewDecoderWithoutBOMHandlingInto(*decoder);
if (success) {
ccs[i].cupper = upper;
ccs[i].clower = lower;
} else {
ccs[i].cupper = i;
ccs[i].clower = i;
}
if (ccs[i].clower != (unsigned char)i)
ccs[i].ccase = true;
else
ccs[i].ccase = false;
}
return ccs;
return moz_hunspell_GetCurrentCS(es.c_str());
}
#endif
@ -2460,7 +2373,7 @@ unsigned short unicodetoupper(unsigned short c, int langnum) {
return static_cast<unsigned short>(u_toupper(c));
#else
#ifdef MOZILLA_CLIENT
return ToUpperCase((char16_t)c);
return moz_hunspell_ToUpperCase((char16_t)c);
#else
return (utf_tbl) ? utf_tbl[c].cupper : c;
#endif
@ -2477,7 +2390,7 @@ unsigned short unicodetolower(unsigned short c, int langnum) {
return static_cast<unsigned short>(u_tolower(c));
#else
#ifdef MOZILLA_CLIENT
return ToLowerCase((char16_t)c);
return moz_hunspell_ToLowerCase((char16_t)c);
#else
return (utf_tbl) ? utf_tbl[c].clower : c;
#endif

View File

@ -82,10 +82,6 @@
#include "w_char.hxx"
#include "htypes.hxx"
#ifdef MOZILLA_CLIENT
#include "nscore.h" // for mozalloc headers
#endif
// casing
#define NOCAP 0
#define INITCAP 1

View File

@ -72,6 +72,6 @@
#ifndef FILEMGR_HXX_
#define FILEMGR_HXX_
#include "mozHunspellFileMgrSandbox.h"
#include "mozHunspellRLBoxSandbox.h"
#endif

View File

@ -5,7 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
'../glue/mozHunspellFileMgrSandbox.cpp',
'../glue/mozHunspellRLBoxSandbox.cpp',
'affentry.cxx',
'affixmgr.cxx',
'csutil.cxx',