Skip to content

Commit

Permalink
Do not validate language tags
Browse files Browse the repository at this point in the history
Dictionaries named with invalid tags (e.g. “fr-toutesvariantes”) are found
in the wild. Pass the problem on to consumers; Enchant should permit these
tags.
  • Loading branch information
rrthomas committed Sep 24, 2023
1 parent 7a9786e commit c7648ec
Show file tree
Hide file tree
Showing 6 changed files with 14 additions and 89 deletions.
2 changes: 1 addition & 1 deletion src/enchant.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ to decide which spelling provider to use for particular languages.
The per-user file takes precedence.
.PP
The ordering file takes the form \fIlanguage_tag:<comma-separated list of spelling
providers>\fR. The language tag is an IETF BCP 47 language tag, typically of the form \fICOUNTRY_LANGUAGE\fR.
providers>\fR. The language tag is typically an IETF BCP 47 language tag of the form \fICOUNTRY_LANGUAGE\fR.
To see what dictionaries are available, run \fIenchant-lsmod-@ENCHANT_MAJOR_VERSION@\fR. \(oq*\(cq is
used to mean \(lquse this ordering for all languages, unless instructed otherwise.\(rq For example:
.IP
Expand Down
46 changes: 13 additions & 33 deletions src/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,20 +157,6 @@ enchant_get_conf_dirs (void)
/********************************************************************************/
/********************************************************************************/

/* returns TRUE if tag is valid
* for requires alphanumeric ASCII or underscore
*/
static G_GNUC_PURE int
enchant_is_valid_dictionary_tag(const char * const tag)
{
const char * it;
for (it = tag; *it; ++it)
if(!g_ascii_isalnum(*it) && *it != '_')
return 0;

return it != tag; /*empty tag invalid*/
}

static char *
enchant_normalize_dictionary_tag (const char * const dict_tag)
{
Expand Down Expand Up @@ -1015,9 +1001,7 @@ enchant_broker_request_dict_with_pwl (EnchantBroker * broker, const char *const
enchant_broker_clear_error (broker);

char * normalized_tag = enchant_normalize_dictionary_tag (tag);
if(!enchant_is_valid_dictionary_tag(normalized_tag))
enchant_broker_set_error (broker, "invalid tag character found");
else if ((dict = _enchant_broker_request_dict (broker, normalized_tag, pwl)) == NULL)
if ((dict = _enchant_broker_request_dict (broker, normalized_tag, pwl)) == NULL)
{
char * iso_639_only_tag = enchant_iso_639_from_tag (normalized_tag);
if (iso_639_only_tag == NULL) {
Expand Down Expand Up @@ -1088,20 +1072,18 @@ enchant_broker_list_dicts (EnchantBroker * broker, EnchantDictDescribeFn fn, voi
{
const char * tag = dicts[i];
g_debug("tag %s", tag);
if (enchant_is_valid_dictionary_tag (tag)) {
GSList *providers = enchant_get_ordered_providers (broker, tag);
gint this_priority = g_slist_index (providers, provider);
g_debug("priority %d", this_priority);
if (this_priority != -1) {
gint min_priority = this_priority + 1;
gpointer ptr = g_hash_table_lookup (tag_map, tag);
if (ptr != NULL)
min_priority = g_slist_index (providers, ptr);
if (this_priority < min_priority)
g_hash_table_insert (tag_map, strdup (tag), provider);
}
g_slist_free (providers);
GSList *providers = enchant_get_ordered_providers (broker, tag);
gint this_priority = g_slist_index (providers, provider);
g_debug("priority %d", this_priority);
if (this_priority != -1) {
gint min_priority = this_priority + 1;
gpointer ptr = g_hash_table_lookup (tag_map, tag);
if (ptr != NULL)
min_priority = g_slist_index (providers, ptr);
if (this_priority < min_priority)
g_hash_table_insert (tag_map, strdup (tag), provider);
}
g_slist_free (providers);
}

g_strfreev (dicts);
Expand Down Expand Up @@ -1203,9 +1185,7 @@ enchant_broker_dict_exists (EnchantBroker * broker, const char * const tag)
char * normalized_tag = enchant_normalize_dictionary_tag (tag);
int exists = 0;

if(!enchant_is_valid_dictionary_tag(normalized_tag))
enchant_broker_set_error (broker, "invalid tag character found");
else if ((exists = _enchant_broker_dict_exists (broker, normalized_tag)) == 0)
if ((exists = _enchant_broker_dict_exists (broker, normalized_tag)) == 0)
{
char * iso_639_only_tag = enchant_iso_639_from_tag (normalized_tag);
if (iso_639_only_tag == NULL) {
Expand Down
7 changes: 0 additions & 7 deletions tests/broker/enchant_broker_dict_exists_tests.i
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,3 @@ TEST_FIXTURE(EnchantBrokerDictExistsTestFixture,
{
CHECK_EQUAL(0, enchant_broker_dict_exists (_broker, ""));
}

TEST_FIXTURE(EnchantBrokerDictExistsTestFixture,
EnchantBrokerDictExists_InvalidTag_0_ErrorSet)
{
CHECK_EQUAL(0, enchant_broker_dict_exists (_broker, "en~US"));
CHECK(NULL != enchant_broker_get_error(_broker));
}
32 changes: 0 additions & 32 deletions tests/broker/enchant_broker_list_dicts_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,31 +79,6 @@ struct EnchantBrokerListDictionaries_TestFixture : EnchantBrokerListDictionaries
{ }
};

static char **
InvalidTagEnGbListDictionaries (EnchantProvider *,
size_t * out_n_dicts)
{
*out_n_dicts = 2;
char** out_list = g_new0 (char *, *out_n_dicts + 1);
out_list[0] = g_strdup ("en_GB");
out_list[1] = g_strdup ("en-GB");

return out_list;
}

static void List_Dictionaries_InvalidTag_ProviderConfiguration (EnchantProvider * me, const char *)
{
me->list_dicts=InvalidTagEnGbListDictionaries;
}

struct EnchantBrokerListDictionaries_ProviderReturnsInvalidTag_TestFixture : EnchantBrokerListDictionaries_TestFixtureBase
{
//Setup
EnchantBrokerListDictionaries_ProviderReturnsInvalidTag_TestFixture():
EnchantBrokerListDictionaries_TestFixtureBase(List_Dictionaries_InvalidTag_ProviderConfiguration)
{ }
};


static char **
DuplicateEnGbListDictionaries (EnchantProvider *,
Expand Down Expand Up @@ -218,10 +193,3 @@ TEST_FIXTURE(EnchantBrokerListDictionaries_ProviderDuplicateTags_TestFixture,
enchant_broker_list_dicts(_broker, EnchantDictionaryDescribeCallback, &_dictionaryList);
CHECK_EQUAL((unsigned int)1, _dictionaryList.size());
}

TEST_FIXTURE(EnchantBrokerListDictionaries_ProviderReturnsInvalidTag_TestFixture,
EnchantBrokerListDictionaries_ProviderReturnsInvalidTag)
{
enchant_broker_list_dicts(_broker, EnchantDictionaryDescribeCallback, &_dictionaryList);
CHECK_EQUAL((unsigned int)1, _dictionaryList.size());
}
8 changes: 0 additions & 8 deletions tests/broker/enchant_broker_request_dict_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,14 +207,6 @@ TEST_FIXTURE(EnchantBrokerRequestDictionary_TestFixture,

}

TEST_FIXTURE(EnchantBrokerRequestDictionary_TestFixture,
EnchantBrokerRequestDictionary_InvalidTag_NULL_ErrorSet)
{
_dict = enchant_broker_request_dict(_broker, "en~US");
CHECK_EQUAL((void*)NULL, _dict);
CHECK(NULL != enchant_broker_get_error(_broker));
}

TEST_FIXTURE(EnchantBrokerTestFixture,
EnchantBrokerRequestDictionary_ProviderLacksListDictionaries_CallbackNeverCalled)
{
Expand Down
8 changes: 0 additions & 8 deletions tests/broker/enchant_broker_request_dict_with_pwl_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,3 @@ TEST_FIXTURE(EnchantBrokerRequestDictionaryWithPwl_TestFixture,
CHECK(!requestDictionaryCalled);

}

TEST_FIXTURE(EnchantBrokerRequestDictionaryWithPwl_TestFixture,
EnchantBrokerRequestDictionaryWithPwl_InvalidTag_NULL_ErrorSet)
{
_dict = enchant_broker_request_dict_with_pwl(_broker, "en~US", _pwlFileName.c_str());
CHECK_EQUAL((void*)NULL, _dict);
CHECK(NULL != enchant_broker_get_error(_broker));
}

0 comments on commit c7648ec

Please sign in to comment.