CVE-2015-5330: Fix handling of unicode near string endings
[samba.git] / lib / util / charset / util_str.c
1 /*
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-2001
5    Copyright (C) Simo Sorce 2001
6    Copyright (C) Andrew Bartlett 2011
7    Copyright (C) Jeremy Allison  1992-2007
8    Copyright (C) Martin Pool     2003
9    Copyright (C) James Peach     2006
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "system/locale.h"
27
28 #ifdef strcasecmp
29 #undef strcasecmp
30 #endif
31
32 /**
33  Case insensitive string compararison, handle specified for testing
34 **/
35 _PUBLIC_ int strcasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
36                                  const char *s1, const char *s2)
37 {
38         codepoint_t c1=0, c2=0;
39         size_t size1, size2;
40
41         /* handle null ptr comparisons to simplify the use in qsort */
42         if (s1 == s2) return 0;
43         if (s1 == NULL) return -1;
44         if (s2 == NULL) return 1;
45
46         while (*s1 && *s2) {
47                 c1 = next_codepoint_handle(iconv_handle, s1, &size1);
48                 c2 = next_codepoint_handle(iconv_handle, s2, &size2);
49
50                 if (c1 == INVALID_CODEPOINT ||
51                     c2 == INVALID_CODEPOINT) {
52                         return strcasecmp(s1, s2);
53                 }
54
55                 s1 += size1;
56                 s2 += size2;
57
58                 if (c1 == c2) {
59                         continue;
60                 }
61
62                 if (toupper_m(c1) != toupper_m(c2)) {
63                         return c1 - c2;
64                 }
65         }
66
67         return *s1 - *s2;
68 }
69
70 /**
71  Case insensitive string compararison
72 **/
73 _PUBLIC_ int strcasecmp_m(const char *s1, const char *s2)
74 {
75         struct smb_iconv_handle *iconv_handle = get_iconv_handle();
76         return strcasecmp_m_handle(iconv_handle, s1, s2);
77 }
78
79 /**
80  Case insensitive string compararison, length limited, handle specified for testing
81 **/
82 _PUBLIC_ int strncasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
83                                   const char *s1, const char *s2, size_t n)
84 {
85         codepoint_t c1=0, c2=0;
86         size_t size1, size2;
87
88         /* handle null ptr comparisons to simplify the use in qsort */
89         if (s1 == s2) return 0;
90         if (s1 == NULL) return -1;
91         if (s2 == NULL) return 1;
92
93         while (*s1 && *s2 && n) {
94                 n--;
95
96                 c1 = next_codepoint_handle(iconv_handle, s1, &size1);
97                 c2 = next_codepoint_handle(iconv_handle, s2, &size2);
98
99                 if (c1 == INVALID_CODEPOINT ||
100                     c2 == INVALID_CODEPOINT) {
101                         /*
102                          * n was specified in characters,
103                          * now we must convert it to bytes.
104                          * As bytes are the smallest
105                          * character unit, the following
106                          * increment and strncasecmp is always
107                          * safe.
108                          *
109                          * The source string was already known
110                          * to be n characters long, so we are
111                          * guaranteed to be able to look at the
112                          * (n remaining + size1) bytes from the
113                          * s1 position).
114                          */
115                         n += size1;
116                         return strncasecmp(s1, s2, n);
117                 }
118
119                 s1 += size1;
120                 s2 += size2;
121
122                 if (c1 == c2) {
123                         continue;
124                 }
125
126                 if (toupper_m(c1) != toupper_m(c2)) {
127                         return c1 - c2;
128                 }
129         }
130
131         if (n == 0) {
132                 return 0;
133         }
134
135         return *s1 - *s2;
136 }
137
138 /**
139  Case insensitive string compararison, length limited
140 **/
141 _PUBLIC_ int strncasecmp_m(const char *s1, const char *s2, size_t n)
142 {
143         struct smb_iconv_handle *iconv_handle = get_iconv_handle();
144         return strncasecmp_m_handle(iconv_handle, s1, s2, n);
145 }
146
147 /**
148  * Compare 2 strings.
149  *
150  * @note The comparison is case-insensitive.
151  **/
152 _PUBLIC_ bool strequal_m(const char *s1, const char *s2)
153 {
154         return strcasecmp_m(s1,s2) == 0;
155 }
156
157 /**
158  Compare 2 strings (case sensitive).
159 **/
160 _PUBLIC_ bool strcsequal(const char *s1,const char *s2)
161 {
162         if (s1 == s2)
163                 return true;
164         if (!s1 || !s2)
165                 return false;
166
167         return strcmp(s1,s2) == 0;
168 }
169
170 /**
171  * Calculate the number of units (8 or 16-bit, depending on the
172  * destination charset), that would be needed to convert the input
173  * string which is expected to be in in src_charset encoding to the
174  * destination charset (which should be a unicode charset).
175  */
176 _PUBLIC_ size_t strlen_m_ext_handle(struct smb_iconv_handle *ic,
177                                     const char *s, charset_t src_charset, charset_t dst_charset)
178 {
179         size_t count = 0;
180
181 #ifdef DEVELOPER
182         switch (dst_charset) {
183         case CH_DOS:
184         case CH_UNIX:
185                 smb_panic("cannot call strlen_m_ext() with a variable dest charset (must be UTF16* or UTF8)");
186         default:
187                 break;
188         }
189
190         switch (src_charset) {
191         case CH_UTF16LE:
192         case CH_UTF16BE:
193                 smb_panic("cannot call strlen_m_ext() with a UTF16 src charset (must be DOS, UNIX, DISPLAY or UTF8)");
194         default:
195                 break;
196         }
197 #endif
198         if (!s) {
199                 return 0;
200         }
201
202         while (*s && !(((uint8_t)*s) & 0x80)) {
203                 s++;
204                 count++;
205         }
206
207         if (!*s) {
208                 return count;
209         }
210
211         while (*s) {
212                 size_t c_size;
213                 codepoint_t c = next_codepoint_handle_ext(ic, s, strnlen(s, 5),
214                                                           src_charset, &c_size);
215                 s += c_size;
216
217                 switch (dst_charset) {
218                 case CH_UTF16LE:
219                 case CH_UTF16BE:
220                 case CH_UTF16MUNGED:
221                         if (c < 0x10000) {
222                                 /* Unicode char fits into 16 bits. */
223                                 count += 1;
224                         } else {
225                                 /* Double-width unicode char - 32 bits. */
226                                 count += 2;
227                         }
228                         break;
229                 case CH_UTF8:
230                         /*
231                          * this only checks ranges, and does not
232                          * check for invalid codepoints
233                          */
234                         if (c < 0x80) {
235                                 count += 1;
236                         } else if (c < 0x800) {
237                                 count += 2;
238                         } else if (c < 0x10000) {
239                                 count += 3;
240                         } else {
241                                 count += 4;
242                         }
243                         break;
244                 default:
245                         /*
246                          * non-unicode encoding:
247                          * assume that each codepoint fits into
248                          * one unit in the destination encoding.
249                          */
250                         count += 1;
251                 }
252         }
253
254         return count;
255 }
256
257 /**
258  * Calculate the number of units (8 or 16-bit, depending on the
259  * destination charset), that would be needed to convert the input
260  * string which is expected to be in in src_charset encoding to the
261  * destination charset (which should be a unicode charset).
262  */
263 _PUBLIC_ size_t strlen_m_ext(const char *s, charset_t src_charset, charset_t dst_charset)
264 {
265         struct smb_iconv_handle *ic = get_iconv_handle();
266         return strlen_m_ext_handle(ic, s, src_charset, dst_charset);
267 }
268
269 _PUBLIC_ size_t strlen_m_ext_term(const char *s, const charset_t src_charset,
270                                   const charset_t dst_charset)
271 {
272         if (!s) {
273                 return 0;
274         }
275         return strlen_m_ext(s, src_charset, dst_charset) + 1;
276 }
277
278 /**
279  * Calculate the number of 16-bit units that would be needed to convert
280  * the input string which is expected to be in CH_UNIX encoding to UTF16.
281  *
282  * This will be the same as the number of bytes in a string for single
283  * byte strings, but will be different for multibyte.
284  */
285 _PUBLIC_ size_t strlen_m(const char *s)
286 {
287         return strlen_m_ext(s, CH_UNIX, CH_UTF16LE);
288 }
289
290 /**
291    Work out the number of multibyte chars in a string, including the NULL
292    terminator.
293 **/
294 _PUBLIC_ size_t strlen_m_term(const char *s)
295 {
296         if (!s) {
297                 return 0;
298         }
299
300         return strlen_m(s) + 1;
301 }
302
303 /*
304  * Weird helper routine for the winreg pipe: If nothing is around, return 0,
305  * if a string is there, include the terminator.
306  */
307
308 _PUBLIC_ size_t strlen_m_term_null(const char *s)
309 {
310         size_t len;
311         if (!s) {
312                 return 0;
313         }
314         len = strlen_m(s);
315         if (len == 0) {
316                 return 0;
317         }
318
319         return len+1;
320 }
321
322 /**
323  Strchr and strrchr_m are a bit complex on general multi-byte strings.
324 **/
325 _PUBLIC_ char *strchr_m(const char *src, char c)
326 {
327         const char *s;
328         struct smb_iconv_handle *ic = get_iconv_handle();
329         if (src == NULL) {
330                 return NULL;
331         }
332         /* characters below 0x3F are guaranteed to not appear in
333            non-initial position in multi-byte charsets */
334         if ((c & 0xC0) == 0) {
335                 return strchr(src, c);
336         }
337
338         /* this is quite a common operation, so we want it to be
339            fast. We optimise for the ascii case, knowing that all our
340            supported multi-byte character sets are ascii-compatible
341            (ie. they match for the first 128 chars) */
342
343         for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
344                 if (*s == c)
345                         return discard_const_p(char, s);
346         }
347
348         if (!*s)
349                 return NULL;
350
351 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
352         /* With compose characters we must restart from the beginning. JRA. */
353         s = src;
354 #endif
355
356         while (*s) {
357                 size_t size;
358                 codepoint_t c2 = next_codepoint_handle(ic, s, &size);
359                 if (c2 == c) {
360                         return discard_const_p(char, s);
361                 }
362                 s += size;
363         }
364
365         return NULL;
366 }
367
368 /**
369  * Multibyte-character version of strrchr
370  */
371 _PUBLIC_ char *strrchr_m(const char *s, char c)
372 {
373         struct smb_iconv_handle *ic = get_iconv_handle();
374         char *ret = NULL;
375
376         if (s == NULL) {
377                 return NULL;
378         }
379
380         /* characters below 0x3F are guaranteed to not appear in
381            non-initial position in multi-byte charsets */
382         if ((c & 0xC0) == 0) {
383                 return strrchr(s, c);
384         }
385
386         /* this is quite a common operation, so we want it to be
387            fast. We optimise for the ascii case, knowing that all our
388            supported multi-byte character sets are ascii-compatible
389            (ie. they match for the first 128 chars). Also, in Samba
390            we only search for ascii characters in 'c' and that
391            in all mb character sets with a compound character
392            containing c, if 'c' is not a match at position
393            p, then p[-1] > 0x7f. JRA. */
394
395         {
396                 size_t len = strlen(s);
397                 const char *cp = s;
398                 bool got_mb = false;
399
400                 if (len == 0)
401                         return NULL;
402                 cp += (len - 1);
403                 do {
404                         if (c == *cp) {
405                                 /* Could be a match. Part of a multibyte ? */
406                                 if ((cp > s) &&
407                                         (((unsigned char)cp[-1]) & 0x80)) {
408                                         /* Yep - go slow :-( */
409                                         got_mb = true;
410                                         break;
411                                 }
412                                 /* No - we have a match ! */
413                                 return discard_const_p(char , cp);
414                         }
415                 } while (cp-- != s);
416                 if (!got_mb)
417                         return NULL;
418         }
419
420         while (*s) {
421                 size_t size;
422                 codepoint_t c2 = next_codepoint_handle(ic, s, &size);
423                 if (c2 == c) {
424                         ret = discard_const_p(char, s);
425                 }
426                 s += size;
427         }
428
429         return ret;
430 }
431
432 /**
433   return True if any (multi-byte) character is lower case
434 */
435 _PUBLIC_ bool strhaslower_handle(struct smb_iconv_handle *ic,
436                                  const char *string)
437 {
438         while (*string) {
439                 size_t c_size;
440                 codepoint_t s;
441                 codepoint_t t;
442
443                 s = next_codepoint_handle(ic, string, &c_size);
444                 string += c_size;
445
446                 t = toupper_m(s);
447
448                 if (s != t) {
449                         return true; /* that means it has lower case chars */
450                 }
451         }
452
453         return false;
454 }
455
456 _PUBLIC_ bool strhaslower(const char *string)
457 {
458         struct smb_iconv_handle *ic = get_iconv_handle();
459         return strhaslower_handle(ic, string);
460 }
461
462 /**
463   return True if any (multi-byte) character is upper case
464 */
465 _PUBLIC_ bool strhasupper_handle(struct smb_iconv_handle *ic,
466                                  const char *string)
467 {
468         while (*string) {
469                 size_t c_size;
470                 codepoint_t s;
471                 codepoint_t t;
472
473                 s = next_codepoint_handle(ic, string, &c_size);
474                 string += c_size;
475
476                 t = tolower_m(s);
477
478                 if (s != t) {
479                         return true; /* that means it has upper case chars */
480                 }
481         }
482
483         return false;
484 }
485
486 _PUBLIC_ bool strhasupper(const char *string)
487 {
488         struct smb_iconv_handle *ic = get_iconv_handle();
489         return strhasupper_handle(ic, string);
490 }
491
492 /***********************************************************************
493  strstr_m - We convert via ucs2 for now.
494 ***********************************************************************/
495
496 char *strstr_m(const char *src, const char *findstr)
497 {
498         smb_ucs2_t *p;
499         smb_ucs2_t *src_w, *find_w;
500         const char *s;
501         char *s2;
502         char *retp;
503         size_t converted_size, findstr_len = 0;
504
505         TALLOC_CTX *frame; /* Only set up in the iconv case */
506
507         /* for correctness */
508         if (!findstr[0]) {
509                 return discard_const_p(char, src);
510         }
511
512         /* Samba does single character findstr calls a *lot*. */
513         if (findstr[1] == '\0')
514                 return strchr_m(src, *findstr);
515
516         /* We optimise for the ascii case, knowing that all our
517            supported multi-byte character sets are ascii-compatible
518            (ie. they match for the first 128 chars) */
519
520         for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
521                 if (*s == *findstr) {
522                         if (!findstr_len)
523                                 findstr_len = strlen(findstr);
524
525                         if (strncmp(s, findstr, findstr_len) == 0) {
526                                 return discard_const_p(char, s);
527                         }
528                 }
529         }
530
531         if (!*s)
532                 return NULL;
533
534 #if 1 /* def BROKEN_UNICODE_COMPOSE_CHARACTERS */
535         /* 'make check' fails unless we do this */
536
537         /* With compose characters we must restart from the beginning. JRA. */
538         s = src;
539 #endif
540
541         frame = talloc_stackframe();
542
543         if (!push_ucs2_talloc(frame, &src_w, src, &converted_size)) {
544                 DEBUG(0,("strstr_m: src malloc fail\n"));
545                 TALLOC_FREE(frame);
546                 return NULL;
547         }
548
549         if (!push_ucs2_talloc(frame, &find_w, findstr, &converted_size)) {
550                 DEBUG(0,("strstr_m: find malloc fail\n"));
551                 TALLOC_FREE(frame);
552                 return NULL;
553         }
554
555         p = strstr_w(src_w, find_w);
556
557         if (!p) {
558                 TALLOC_FREE(frame);
559                 return NULL;
560         }
561
562         *p = 0;
563         if (!pull_ucs2_talloc(frame, &s2, src_w, &converted_size)) {
564                 TALLOC_FREE(frame);
565                 DEBUG(0,("strstr_m: dest malloc fail\n"));
566                 return NULL;
567         }
568         retp = discard_const_p(char, (s+strlen(s2)));
569         TALLOC_FREE(frame);
570         return retp;
571 }