mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
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:
parent
615c7cc3b1
commit
523d862fa2
156
extensions/spellcheck/hunspell/glue/RLBoxHunspell.cpp
Normal file
156
extensions/spellcheck/hunspell/glue/RLBoxHunspell.cpp
Normal 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;
|
||||
}
|
50
extensions/spellcheck/hunspell/glue/RLBoxHunspell.h
Normal file
50
extensions/spellcheck/hunspell/glue/RLBoxHunspell.h
Normal 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
|
45
extensions/spellcheck/hunspell/glue/RLBoxHunspellTypes.h
Normal file
45
extensions/spellcheck/hunspell/glue/RLBoxHunspellTypes.h
Normal 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
|
158
extensions/spellcheck/hunspell/glue/hunspell_csutil.cxx
Normal file
158
extensions/spellcheck/hunspell/glue/hunspell_csutil.cxx
Normal 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;
|
||||
}
|
87
extensions/spellcheck/hunspell/glue/hunspell_csutil.hxx
Normal file
87
extensions/spellcheck/hunspell/glue/hunspell_csutil.hxx
Normal 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
|
@ -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
|
||||
|
@ -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 =
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
@ -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)
|
||||
}
|
213
extensions/spellcheck/hunspell/glue/mozHunspellRLBoxHost.cpp
Normal file
213
extensions/spellcheck/hunspell/glue/mozHunspellRLBoxHost.cpp
Normal 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;
|
||||
});
|
||||
}
|
117
extensions/spellcheck/hunspell/glue/mozHunspellRLBoxHost.h
Normal file
117
extensions/spellcheck/hunspell/glue/mozHunspellRLBoxHost.h
Normal 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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -72,6 +72,6 @@
|
||||
#ifndef FILEMGR_HXX_
|
||||
#define FILEMGR_HXX_
|
||||
|
||||
#include "mozHunspellFileMgrSandbox.h"
|
||||
#include "mozHunspellRLBoxSandbox.h"
|
||||
|
||||
#endif
|
||||
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user