Line data Source code
1 : /* bidi.c - IDNA right to left checking functions 2 : Copyright (C) 2011-2024 Simon Josefsson 3 : 4 : Libidn2 is free software: you can redistribute it and/or modify it 5 : under the terms of either: 6 : 7 : * the GNU Lesser General Public License as published by the Free 8 : Software Foundation; either version 3 of the License, or (at 9 : your option) any later version. 10 : 11 : or 12 : 13 : * the GNU General Public License as published by the Free 14 : Software Foundation; either version 2 of the License, or (at 15 : your option) any later version. 16 : 17 : or both in parallel, as here. 18 : 19 : This program is distributed in the hope that it will be useful, 20 : but WITHOUT ANY WARRANTY; without even the implied warranty of 21 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 : GNU General Public License for more details. 23 : 24 : You should have received copies of the GNU General Public License and 25 : the GNU Lesser General Public License along with this program. If 26 : not, see <http://www.gnu.org/licenses/>. 27 : */ 28 : 29 : #include <config.h> 30 : 31 : #include "idn2.h" 32 : 33 : #include <sys/types.h> 34 : #include <stdbool.h> 35 : 36 : #include "bidi.h" 37 : 38 : #include <unictype.h> 39 : 40 : static bool 41 544800 : _isBidi (const uint32_t *label, size_t llen) 42 : { 43 1098708 : for (; (ssize_t) llen > 0; llen--) 44 : { 45 565590 : int bc = uc_bidi_category (*label++); 46 : 47 565590 : if (bc == UC_BIDI_R || bc == UC_BIDI_AL || bc == UC_BIDI_AN) 48 11682 : return 1; 49 : } 50 : 51 533118 : return 0; 52 : } 53 : 54 : /* IDNA2008 BIDI check (RFC 5893) */ 55 : int 56 544800 : _idn2_bidi (const uint32_t *label, size_t llen) 57 : { 58 : int bc; 59 544800 : int endok = 1; 60 : 61 544800 : if (!_isBidi (label, llen)) 62 533118 : return IDN2_OK; 63 : 64 : // 2.1 65 11682 : switch ((bc = uc_bidi_category (*label))) 66 : { 67 247 : case UC_BIDI_L: 68 : // check 2.5 & 2.6 69 1642 : for (size_t it = 1; it < llen; it++) 70 : { 71 1642 : bc = uc_bidi_category (label[it]); 72 : 73 1642 : if (bc == UC_BIDI_L || bc == UC_BIDI_EN || bc == UC_BIDI_NSM) 74 : { 75 1302 : endok = 1; 76 : } 77 : else 78 : { 79 340 : if (bc != UC_BIDI_ES && bc != UC_BIDI_CS && bc != UC_BIDI_ET 80 310 : && bc != UC_BIDI_ON && bc != UC_BIDI_BN) 81 : { 82 : /* printf("LTR label contains invalid code point\n"); */ 83 247 : return IDN2_BIDI; 84 : } 85 93 : endok = 0; 86 : } 87 : } 88 : /* printf("LTR label ends with invalid code point\n"); */ 89 0 : return endok ? IDN2_OK : IDN2_BIDI; 90 : 91 10827 : case UC_BIDI_R: 92 : case UC_BIDI_AL: 93 : // check 2.2, 2.3, 2.4 94 : /* printf("Label[0]=%04X: %s\n", label[0], uc_bidi_category_name(bc)); */ 95 17574 : for (size_t it = 1; it < llen; it++) 96 : { 97 6932 : bc = uc_bidi_category (label[it]); 98 : 99 : /* printf("Label[%d]=%04X: %s\n", (int) it, label[it], uc_bidi_category_name(bc)); */ 100 6932 : if (bc == UC_BIDI_R || bc == UC_BIDI_AL || bc == UC_BIDI_EN 101 1104 : || bc == UC_BIDI_AN || bc == UC_BIDI_NSM) 102 : { 103 6139 : endok = 1; 104 : } 105 : else 106 : { 107 793 : if (bc != UC_BIDI_ES && bc != UC_BIDI_CS && bc != UC_BIDI_ET 108 454 : && bc != UC_BIDI_ON && bc != UC_BIDI_BN) 109 : { 110 : /* printf("RTL label contains invalid code point\n"); */ 111 185 : return IDN2_BIDI; 112 : } 113 608 : endok = 0; 114 : } 115 : } 116 : /* printf("RTL label ends with invalid code point\n"); */ 117 10642 : return endok ? IDN2_OK : IDN2_BIDI; 118 : 119 608 : default: 120 : /* printf("Label begins with invalid BIDI class %s\n", uc_bidi_category_name(bc)); */ 121 608 : return IDN2_BIDI; 122 : } 123 : }