fix(developer): prevent non-BMP characters in key part of rule

Currently, keys must be a UTF-16 code unit or a virtual key. Non-BMP
characters are unsupported. Technically, there is space available in the
.kmx `COMP_KEY` structure to accommodate UTF-32 codepoints, from
kmx_file.h:

    KMX_WORD_unaligned Key;
    KMX_WORD_unaligned _reserved;

However, the utility of this is almost nil, as it is very unlikely we
will encounter base keyboards (for mnemonic layouts) that generate any
characters outside the BMP, so there is little value in adding support
for this at this time.

The compiler will generate an error if this is encountered.

Fixes: #11643
This commit is contained in:
Marc Durdin 2024-06-12 16:23:32 +07:00
parent ce49f12af9
commit 2dcc8fb948
4 changed files with 16 additions and 4 deletions

View file

@ -179,6 +179,7 @@
#define CERR_ExtendedStringTooLong 0x00004076
#define CERR_VirtualKeyExpansionTooLong 0x00004077
#define CERR_CharacterRangeTooLong 0x00004078
#define CERR_NonBMPCharactersNotSupportedInKeySection 0x00004079
#define CWARN_TooManyWarnings 0x00002080
#define CWARN_OldVersion 0x00002081

View file

@ -571,6 +571,8 @@ export class KmnCompilerMessages {
static ERROR_CharacterRangeTooLong = SevError | 0x078;
static Error_CharacterRangeTooLong = () => m(this.ERROR_CharacterRangeTooLong, `Character range is too large and cannot be expanded`);
static ERROR_NonBMPCharactersNotSupportedInKeySection = SevError | 0x079;
static Error_NonBMPCharactersNotSupportedInKeySection = () => m(this.ERROR_NonBMPCharactersNotSupportedInKeySection, `Characters with codepoints over U+FFFF are not supported in the key part of the rule`);
static WARN_TooManyWarnings = SevWarn | 0x080;
static Warn_TooManyWarnings = () => m(this.WARN_TooManyWarnings, `Too many warnings or errors`);

View file

@ -115,6 +115,7 @@ const struct CompilerError CompilerErrors[] = {
{ CERR_ExtendedStringTooLong , "Extended string is too long" },
{ CERR_VirtualKeyExpansionTooLong , "Virtual key expansion is too large" },
{ CERR_CharacterRangeTooLong , "Character range is too large and cannot be expanded" },
{ CERR_NonBMPCharactersNotSupportedInKeySection , "Characters with codepoints over U+FFFF are not supported in the key part of the rule" },
{ CHINT_UnreachableRule , "This rule will never be matched as another rule takes precedence"},
{ CHINT_NonUnicodeFile , "Keyman Developer has detected that the file has ANSI encoding. Consider converting this file to UTF-8"},

View file

@ -1210,7 +1210,7 @@ int GetCompileTargetsFromTargetsStore(const KMX_WCHAR* store) {
KMX_BOOL IsValidKeyboardVersion(KMX_WCHAR *dpString) { // I4140
/**
version format: /^\d+(\.\d+)*$/
e.g. 9.0.3, 1.0, 1.2.3.4, 6.2.1.4.6.4, 11.22.3 are all ok;
e.g. 9.0.3, 1.0, 1.2.3.4, 6.2.1.4.6.4, 11.22.3 are all ok;
empty string is not permitted; whitespace is not permitted
*/
@ -1471,7 +1471,14 @@ KMX_DWORD ProcessKeyLineImpl(PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_BOOL IsUnico
str = p + 1;
if ((msg = GetXString(fk, str, u">", pklKey, GLOBAL_BUFSIZE - 1, (int)(str - pp), &p, TRUE, IsUnicode)) != CERR_None) return msg;
if (pklKey[0] == 0) return CERR_ZeroLengthString;
if(Uni_IsSurrogate1(pklKey[0])) {
// #11643: non-BMP characters do not makes sense for key codes
return CERR_NonBMPCharactersNotSupportedInKeySection;
}
if (xstrlen(pklKey) > 1) AddWarning(CWARN_KeyBadLength);
} else {
if ((msg = GetXString(fk, str, u">", pklIn, GLOBAL_BUFSIZE - 1, (int)(str - pp), &p, TRUE, IsUnicode)) != CERR_None) return msg;
@ -1653,9 +1660,10 @@ KMX_DWORD ExpandKp(PFILE_KEYBOARD fk, PFILE_KEY kpp, KMX_DWORD storeIndex)
default:
return CERR_CodeInvalidInKeyStore;
}
}
else
{
} else if(Uni_IsSurrogate1(*pn)) {
// #11643: non-BMP characters do not makes sense for key codes
return CERR_NonBMPCharactersNotSupportedInKeySection;
} else {
k->Key = *pn; // set the key to store offset.
k->ShiftFlags = 0;
}