Ignore invalid font features when parsing config

This commit is contained in:
Kovid Goyal 2020-01-07 09:19:01 +05:30
parent 14560b008a
commit 8a5f189213
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 41 additions and 7 deletions

View File

@ -410,6 +410,14 @@ def handle_symbol_map(key, val, ans):
ans['symbol_map'].update(parse_symbol_map(val))
class FontFeature(str):
def __new__(cls, name, parsed):
ans = str.__new__(cls, name)
ans.parsed = parsed
return ans
@special_handler
def handle_font_features(key, val, ans):
if val != 'none':
@ -417,7 +425,16 @@ def handle_font_features(key, val, ans):
if len(parts) < 2:
log_error("Ignoring invalid font_features {}".format(val))
else:
ans['font_features'][parts[0]] = parts[1:]
features = []
for feat in parts[1:]:
try:
parsed = defines.parse_font_feature(feat)
except ValueError:
log_error('Ignoring invalid font feature: {}'.format(feat))
else:
features.append(FontFeature(feat, parsed))
if features:
ans['font_features'][parts[0]] = tuple(features)
@special_handler

View File

@ -355,17 +355,17 @@ init_font(Font *f, PyObject *face, bool bold, bool italic, bool emoji_presentati
const char *psname = postscript_name_for_face(face);
if (font_feature_settings != NULL){
PyObject* o = PyDict_GetItemString(font_feature_settings, psname);
if (o != NULL) {
Py_ssize_t len = PySequence_Size(o);
if (o != NULL && PyTuple_Check(o)) {
Py_ssize_t len = PyTuple_GET_SIZE(o);
if (len > 0) {
f->num_ffs_hb_features = len + 1;
f->ffs_hb_features = calloc(f->num_ffs_hb_features, sizeof(hb_feature_t));
if (!f->ffs_hb_features) return false;
for (Py_ssize_t i = 0; i < len; i++) {
PyObject* item = PySequence_GetItem(o, i);
if (!PyUnicode_Check(item)) fatal("A font feature is not a unicode string");
if (!hb_feature_from_string(PyUnicode_AsUTF8(item), -1, &f->ffs_hb_features[i])) {
fatal("Invalid font feature: %s", PyUnicode_AsUTF8(item));
PyObject* parsed = PyObject_GetAttrString(PyTuple_GET_ITEM(o, i), "parsed");
if (parsed) {
memcpy(f->ffs_hb_features + i, PyBytes_AS_STRING(parsed), sizeof(hb_feature_t));
Py_DECREF(parsed);
}
}
memcpy(f->ffs_hb_features + len, &hb_features[CALT_FEATURE], sizeof(hb_feature_t));
@ -1455,9 +1455,26 @@ free_font_data(PyObject *self UNUSED, PyObject *args UNUSED) {
Py_RETURN_NONE;
}
static PyObject*
parse_font_feature(PyObject *self UNUSED, PyObject *feature) {
if (!PyUnicode_Check(feature)) {
PyErr_SetString(PyExc_TypeError, "feature must be a unicode object");
return NULL;
}
PyObject *ans = PyBytes_FromStringAndSize(NULL, sizeof(hb_feature_t));
if (!ans) return NULL;
if (!hb_feature_from_string(PyUnicode_AsUTF8(feature), -1, (hb_feature_t*)PyBytes_AS_STRING(ans))) {
Py_CLEAR(ans);
PyErr_Format(PyExc_ValueError, "%U is not a valid font feature", feature);
return NULL;
}
return ans;
}
static PyMethodDef module_methods[] = {
METHODB(set_font_data, METH_VARARGS),
METHODB(free_font_data, METH_NOARGS),
METHODB(parse_font_feature, METH_O),
METHODB(create_test_font_group, METH_VARARGS),
METHODB(sprite_map_set_layout, METH_VARARGS),
METHODB(test_sprite_position_for, METH_VARARGS),