diff --git a/developer/src/common/include/kmn_compiler_errors.h b/developer/src/common/include/kmn_compiler_errors.h index 4973f58abe..78ab21efa1 100644 --- a/developer/src/common/include/kmn_compiler_errors.h +++ b/developer/src/common/include/kmn_compiler_errors.h @@ -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 diff --git a/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts b/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts index 32dac9fb66..ec7c81a7a8 100644 --- a/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts +++ b/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts @@ -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`); diff --git a/developer/src/kmcmplib/src/CompMsg.cpp b/developer/src/kmcmplib/src/CompMsg.cpp index 86a9b4d475..e075a4c808 100644 --- a/developer/src/kmcmplib/src/CompMsg.cpp +++ b/developer/src/kmcmplib/src/CompMsg.cpp @@ -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"}, diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp index 8d0f11af8f..b014d8d7c8 100644 --- a/developer/src/kmcmplib/src/Compiler.cpp +++ b/developer/src/kmcmplib/src/Compiler.cpp @@ -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; }