1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) NGINX, Inc.
5 */
6
7 #include <nxt_main.h>
8
9
10 nxt_str_t *
nxt_str_alloc(nxt_mp_t * mp,size_t length)11 nxt_str_alloc(nxt_mp_t *mp, size_t length)
12 {
13 nxt_str_t *s;
14
15 /* The string start is allocated aligned to be close to nxt_str_t. */
16 s = nxt_mp_get(mp, sizeof(nxt_str_t) + length);
17
18 if (nxt_fast_path(s != NULL)) {
19 s->length = length;
20 s->start = nxt_pointer_to(s, sizeof(nxt_str_t));
21 }
22
23 return s;
24 }
25
26
27 /*
28 * nxt_str_dup() creates a new string with a copy of a source string.
29 * If length of the source string is zero, then the new string anyway
30 * gets a pointer somewhere in mem_pool.
31 */
32
33 nxt_str_t *
nxt_str_dup(nxt_mp_t * mp,nxt_str_t * dst,const nxt_str_t * src)34 nxt_str_dup(nxt_mp_t *mp, nxt_str_t *dst, const nxt_str_t *src)
35 {
36 u_char *p;
37
38 if (dst == NULL) {
39 /* The string start is allocated aligned to be close to nxt_str_t. */
40 dst = nxt_mp_get(mp, sizeof(nxt_str_t) + src->length);
41 if (nxt_slow_path(dst == NULL)) {
42 return NULL;
43 }
44
45 p = (u_char *) dst;
46 p += sizeof(nxt_str_t);
47 dst->start = p;
48
49 } else {
50 dst->start = nxt_mp_nget(mp, src->length);
51 if (nxt_slow_path(dst->start == NULL)) {
52 return NULL;
53 }
54 }
55
56 nxt_memcpy(dst->start, src->start, src->length);
57 dst->length = src->length;
58
59 return dst;
60 }
61
62
63 /*
64 * nxt_str_cstrz() creates a C style zero-terminated copy of a source
65 * nxt_str_t. The function is intended to create strings suitable
66 * for libc and kernel interfaces so result is pointer to char instead
67 * of u_char to minimize casts.
68 */
69
70 char *
nxt_str_cstrz(nxt_mp_t * mp,const nxt_str_t * src)71 nxt_str_cstrz(nxt_mp_t *mp, const nxt_str_t *src)
72 {
73 char *p, *dst;
74
75 dst = nxt_mp_alloc(mp, src->length + 1);
76
77 if (nxt_fast_path(dst != NULL)) {
78 p = nxt_cpymem(dst, src->start, src->length);
79 *p = '\0';
80 }
81
82 return dst;
83 }
84
85
86 void
nxt_memcpy_lowcase(u_char * dst,const u_char * src,size_t length)87 nxt_memcpy_lowcase(u_char *dst, const u_char *src, size_t length)
88 {
89 u_char c;
90
91 while (length != 0) {
92 c = *src++;
93 *dst++ = nxt_lowcase(c);
94 length--;
95 }
96 }
97
98
99 void
nxt_memcpy_upcase(u_char * dst,const u_char * src,size_t length)100 nxt_memcpy_upcase(u_char *dst, const u_char *src, size_t length)
101 {
102 u_char c;
103
104 while (length != 0) {
105 c = *src++;
106 *dst++ = nxt_upcase(c);
107 length--;
108 }
109 }
110
111
112 u_char *
nxt_cpystr(u_char * dst,const u_char * src)113 nxt_cpystr(u_char *dst, const u_char *src)
114 {
115 for ( ;; ) {
116 *dst = *src;
117
118 if (*dst == '\0') {
119 break;
120 }
121
122 dst++;
123 src++;
124 }
125
126 return dst;
127 }
128
129
130 u_char *
nxt_cpystrn(u_char * dst,const u_char * src,size_t length)131 nxt_cpystrn(u_char *dst, const u_char *src, size_t length)
132 {
133 if (length == 0) {
134 return dst;
135 }
136
137 while (--length != 0) {
138 *dst = *src;
139
140 if (*dst == '\0') {
141 return dst;
142 }
143
144 dst++;
145 src++;
146 }
147
148 *dst = '\0';
149
150 return dst;
151 }
152
153
154 nxt_int_t
nxt_strcasecmp(const u_char * s1,const u_char * s2)155 nxt_strcasecmp(const u_char *s1, const u_char *s2)
156 {
157 u_char c1, c2;
158 nxt_int_t n;
159
160 for ( ;; ) {
161 c1 = *s1++;
162 c2 = *s2++;
163
164 c1 = nxt_lowcase(c1);
165 c2 = nxt_lowcase(c2);
166
167 n = c1 - c2;
168
169 if (n != 0) {
170 return n;
171 }
172
173 if (c1 == 0) {
174 return 0;
175 }
176 }
177 }
178
179
180 nxt_int_t
nxt_strncasecmp(const u_char * s1,const u_char * s2,size_t length)181 nxt_strncasecmp(const u_char *s1, const u_char *s2, size_t length)
182 {
183 u_char c1, c2;
184 nxt_int_t n;
185
186 while (length-- != 0) {
187 c1 = *s1++;
188 c2 = *s2++;
189
190 c1 = nxt_lowcase(c1);
191 c2 = nxt_lowcase(c2);
192
193 n = c1 - c2;
194
195 if (n != 0) {
196 return n;
197 }
198
199 if (c1 == 0) {
200 return 0;
201 }
202 }
203
204 return 0;
205 }
206
207
208 nxt_int_t
nxt_memcasecmp(const void * p1,const void * p2,size_t length)209 nxt_memcasecmp(const void *p1, const void *p2, size_t length)
210 {
211 u_char c1, c2;
212 nxt_int_t n;
213 const u_char *s1, *s2;
214
215 s1 = p1;
216 s2 = p2;
217
218 while (length-- != 0) {
219 c1 = *s1++;
220 c2 = *s2++;
221
222 c1 = nxt_lowcase(c1);
223 c2 = nxt_lowcase(c2);
224
225 n = c1 - c2;
226
227 if (n != 0) {
228 return n;
229 }
230 }
231
232 return 0;
233 }
234
235
236 /*
237 * nxt_memstrn() is intended for search of static substring "ss"
238 * with known length "length" in string "s" limited by parameter "end".
239 * Zeros are ignored in both strings.
240 */
241
242 u_char *
nxt_memstrn(const u_char * s,const u_char * end,const char * ss,size_t length)243 nxt_memstrn(const u_char *s, const u_char *end, const char *ss, size_t length)
244 {
245 u_char c1, c2, *s2;
246
247 s2 = (u_char *) ss;
248 c2 = *s2++;
249 length--;
250
251 while (s < end) {
252 c1 = *s++;
253
254 if (c1 == c2) {
255
256 if (s + length > end) {
257 return NULL;
258 }
259
260 if (nxt_memcmp(s, s2, length) == 0) {
261 return (u_char *) s - 1;
262 }
263 }
264 }
265
266 return NULL;
267 }
268
269
270 /*
271 * nxt_strcasestrn() is intended for caseless search of static substring
272 * "ss" with known length "length" in string "s" limited by parameter "end".
273 * Zeros are ignored in both strings.
274 */
275
276 u_char *
nxt_memcasestrn(const u_char * s,const u_char * end,const char * ss,size_t length)277 nxt_memcasestrn(const u_char *s, const u_char *end, const char *ss,
278 size_t length)
279 {
280 u_char c1, c2, *s2;
281
282 s2 = (u_char *) ss;
283 c2 = *s2++;
284 c2 = nxt_lowcase(c2);
285 length--;
286
287 while (s < end) {
288 c1 = *s++;
289 c1 = nxt_lowcase(c1);
290
291 if (c1 == c2) {
292
293 if (s + length > end) {
294 return NULL;
295 }
296
297 if (nxt_memcasecmp(s, s2, length) == 0) {
298 return (u_char *) s - 1;
299 }
300 }
301 }
302
303 return NULL;
304 }
305
306
307 /*
308 * nxt_rstrstrn() is intended to search for static substring "ss"
309 * with known length "length" in string "s" limited by parameter "end"
310 * in reverse order. Zeros are ignored in both strings.
311 */
312
313 u_char *
nxt_rmemstrn(const u_char * s,const u_char * end,const char * ss,size_t length)314 nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length)
315 {
316 u_char c1, c2;
317 const u_char *s1, *s2;
318
319 s1 = end - length;
320 s2 = (u_char *) ss;
321 c2 = *s2++;
322 length--;
323
324 while (s < s1) {
325 c1 = *s1;
326
327 if (c1 == c2) {
328 if (nxt_memcmp(s1 + 1, s2, length) == 0) {
329 return (u_char *) s1;
330 }
331 }
332
333 s1--;
334 }
335
336 return NULL;
337 }
338
339
340 size_t
nxt_str_strip(u_char * start,u_char * end)341 nxt_str_strip(u_char *start, u_char *end)
342 {
343 u_char *p;
344
345 for (p = end - 1; p >= start; p--) {
346 if (*p != '\r' && *p != '\n') {
347 break;
348 }
349 }
350
351 return (p + 1) - start;
352 }
353
354
355 nxt_int_t
nxt_strverscmp(const u_char * s1,const u_char * s2)356 nxt_strverscmp(const u_char *s1, const u_char *s2)
357 {
358 u_char c1, c2;
359 nxt_int_t diff;
360
361 enum {
362 st_str = 0,
363 st_num,
364 st_zero,
365 st_frac,
366 } state;
367
368 state = st_str;
369
370 for ( ;; ) {
371 c1 = *s1++;
372 c2 = *s2++;
373
374 diff = c1 - c2;
375
376 if (diff != 0) {
377 break;
378 }
379
380 if (c1 == '\0') {
381 return 0;
382 }
383
384 if (!nxt_isdigit(c1)) {
385 state = st_str;
386 continue;
387 }
388
389 if (state == st_str) {
390 state = (c1 != '0') ? st_num : st_zero;
391 continue;
392 }
393
394 if (state == st_zero && c1 != '0') {
395 state = st_frac;
396 continue;
397 }
398 }
399
400 switch (state) {
401
402 case st_str:
403
404 if ((u_char) (c1 - '1') > 8 || (u_char) (c2 - '1') > 8) {
405 return diff;
406 }
407
408 c1 = *s1++;
409 c2 = *s2++;
410
411 /* Fall through. */
412
413 case st_num:
414
415 while (nxt_isdigit(c1) && nxt_isdigit(c2)) {
416 c1 = *s1++;
417 c2 = *s2++;
418 }
419
420 if (nxt_isdigit(c1)) {
421 return 1;
422 }
423
424 if (nxt_isdigit(c2)) {
425 return -1;
426 }
427
428 return diff;
429
430 case st_zero:
431
432 if (c1 == '0' || c2 == '\0') {
433 return -1;
434 }
435
436 if (c2 == '0' || c1 == '\0') {
437 return 1;
438 }
439
440 /* Fall through. */
441
442 case st_frac:
443 default:
444 return diff;
445 }
446 }
447
448
449 nxt_bool_t
nxt_strvers_match(u_char * version,u_char * prefix,size_t length)450 nxt_strvers_match(u_char *version, u_char *prefix, size_t length)
451 {
452 u_char next, last;
453
454 if (length == 0) {
455 return 1;
456 }
457
458 if (nxt_strncmp(version, prefix, length) == 0) {
459
460 next = version[length];
461
462 if (next == '\0') {
463 return 1;
464 }
465
466 last = version[length - 1];
467
468 if (nxt_isdigit(last) != nxt_isdigit(next)) {
469 /* This is a version part boundary. */
470 return 1;
471 }
472 }
473
474 return 0;
475 }
476
477
478 const uint8_t nxt_hex2int[256]
479 nxt_aligned(32) =
480 {
481 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
482 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
483 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
484 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 16, 16, 16, 16, 16,
485 16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
486 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
487 16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
488 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
489 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
490 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
491 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
492 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
493 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
494 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
495 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
496 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
497 };
498
499
500 static const uint32_t nxt_uri_escape[] = {
501 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
502
503 /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
504 0xd000002d, /* 1101 0000 0000 0000 0000 0000 0010 1101 */
505
506 /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
507 0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */
508
509 /* ~}| {zyx wvut srqp onml kjih gfed cba` */
510 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */
511
512 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
513 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
514 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
515 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
516 };
517
518
519 u_char *
nxt_decode_uri(u_char * dst,u_char * src,size_t length)520 nxt_decode_uri(u_char *dst, u_char *src, size_t length)
521 {
522 u_char *end, ch;
523 uint8_t d0, d1;
524
525 nxt_prefetch(&nxt_hex2int['0']);
526
527 end = src + length;
528
529 while (src < end) {
530 ch = *src++;
531
532 if (ch == '%') {
533 if (nxt_slow_path(end - src < 2)) {
534 return NULL;
535 }
536
537 d0 = nxt_hex2int[*src++];
538 d1 = nxt_hex2int[*src++];
539
540 if (nxt_slow_path((d0 | d1) >= 16)) {
541 return NULL;
542 }
543
544 ch = (d0 << 4) + d1;
545 }
546
547 *dst++ = ch;
548 }
549
550 return dst;
551 }
552
553
554 u_char *
nxt_decode_uri_plus(u_char * dst,u_char * src,size_t length)555 nxt_decode_uri_plus(u_char *dst, u_char *src, size_t length)
556 {
557 u_char *end, ch;
558 uint8_t d0, d1;
559
560 nxt_prefetch(&nxt_hex2int['0']);
561
562 end = src + length;
563
564 while (src < end) {
565 ch = *src++;
566
567 switch (ch) {
568 case '%':
569 if (nxt_slow_path(end - src < 2)) {
570 return NULL;
571 }
572
573 d0 = nxt_hex2int[*src++];
574 d1 = nxt_hex2int[*src++];
575
576 if (nxt_slow_path((d0 | d1) >= 16)) {
577 return NULL;
578 }
579
580 ch = (d0 << 4) + d1;
581 break;
582
583 case '+':
584 ch = ' ';
585 break;
586 }
587
588 *dst++ = ch;
589 }
590
591 return dst;
592 }
593
594
595 uintptr_t
nxt_encode_uri(u_char * dst,u_char * src,size_t length)596 nxt_encode_uri(u_char *dst, u_char *src, size_t length)
597 {
598 u_char *end;
599 nxt_uint_t n;
600
601 static const u_char hex[16] = "0123456789ABCDEF";
602
603 end = src + length;
604
605 if (dst == NULL) {
606
607 /* Find the number of the characters to be escaped. */
608
609 n = 0;
610
611 while (src < end) {
612
613 if (nxt_uri_escape[*src >> 5] & (1U << (*src & 0x1f))) {
614 n++;
615 }
616
617 src++;
618 }
619
620 return (uintptr_t) n;
621 }
622
623 while (src < end) {
624
625 if (nxt_uri_escape[*src >> 5] & (1U << (*src & 0x1f))) {
626 *dst++ = '%';
627 *dst++ = hex[*src >> 4];
628 *dst++ = hex[*src & 0xf];
629
630 } else {
631 *dst++ = *src;
632 }
633
634 src++;
635 }
636
637 return (uintptr_t) dst;
638 }
639
640
641 uintptr_t
nxt_encode_complex_uri(u_char * dst,u_char * src,size_t length)642 nxt_encode_complex_uri(u_char *dst, u_char *src, size_t length)
643 {
644 u_char *reserved, *end, ch;
645 nxt_uint_t n;
646
647 static const u_char hex[16] = "0123456789ABCDEF";
648
649 reserved = (u_char *) "?#\0";
650
651 end = src + length;
652
653 if (dst == NULL) {
654
655 /* Find the number of the characters to be escaped. */
656
657 n = 0;
658
659 while (src < end) {
660 ch = *src++;
661
662 if (nxt_uri_escape[ch >> 5] & (1U << (ch & 0x1f))) {
663 if (ch == reserved[0]) {
664 reserved++;
665 continue;
666 }
667
668 if (ch == reserved[1]) {
669 reserved += 2;
670 continue;
671 }
672
673 n++;
674 }
675 }
676
677 return (uintptr_t) n;
678 }
679
680 while (src < end) {
681 ch = *src++;
682
683 if (nxt_uri_escape[ch >> 5] & (1U << (ch & 0x1f))) {
684 if (ch == reserved[0]) {
685 reserved++;
686
687 } else if (ch == reserved[1]) {
688 reserved += 2;
689
690 } else {
691 *dst++ = '%';
692 *dst++ = hex[ch >> 4];
693 *dst++ = hex[ch & 0xf];
694 continue;
695 }
696 }
697
698 *dst++ = ch;
699 }
700
701 return (uintptr_t) dst;
702 }
703
704
705 nxt_bool_t
nxt_is_complex_uri_encoded(u_char * src,size_t length)706 nxt_is_complex_uri_encoded(u_char *src, size_t length)
707 {
708 u_char *reserved, *end, ch;
709 uint8_t d0, d1;
710
711 reserved = (u_char *) "?#\0";
712
713 for (end = src + length; src < end; src++) {
714 ch = *src;
715
716 if (nxt_uri_escape[ch >> 5] & (1U << (ch & 0x1f))) {
717 if (ch == '%') {
718 if (end - src < 2) {
719 return 0;
720 }
721
722 d0 = nxt_hex2int[*++src];
723 d1 = nxt_hex2int[*++src];
724
725 if ((d0 | d1) >= 16) {
726 return 0;
727 }
728
729 continue;
730 }
731
732 if (ch == reserved[0]) {
733 reserved++;
734 continue;
735 }
736
737 if (ch == reserved[1]) {
738 reserved += 2;
739 continue;
740 }
741
742 return 0;
743 }
744 }
745
746 return 1;
747 }
748
749
750 ssize_t
nxt_base64_decode(u_char * dst,u_char * src,size_t length)751 nxt_base64_decode(u_char *dst, u_char *src, size_t length)
752 {
753 u_char *end, *p;
754 size_t pad;
755 uint8_t v1, v2, v3, v4;
756
757 static const uint8_t decode[] = {
758 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
759 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
760 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63,
761 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77,
762 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
763 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77,
764 77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
765 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77,
766
767 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
768 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
769 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
770 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
771 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
772 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
773 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
774 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77
775 };
776
777 end = src + length;
778 pad = (4 - (length % 4)) % 4;
779
780 if (dst == NULL) {
781 if (pad > 2) {
782 return NXT_ERROR;
783 }
784
785 while (src < end) {
786 if (decode[*src] != 77) {
787 src++;
788 continue;
789 }
790
791 if (pad == 0) {
792 pad = end - src;
793
794 if ((pad == 1 || (pad == 2 && src[1] == '=')) && src[0] == '=')
795 {
796 break;
797 }
798 }
799
800 return NXT_ERROR;
801 }
802
803 return (length + 3) / 4 * 3 - pad;
804 }
805
806 nxt_assert(length != 0);
807
808 if (pad == 0) {
809 pad = (end[-1] == '=') + (end[-2] == '=');
810 end -= (pad + 3) & 4;
811
812 } else {
813 end -= 4 - pad;
814 }
815
816 p = dst;
817
818 while (src < end) {
819 v1 = decode[src[0]];
820 v2 = decode[src[1]];
821 v3 = decode[src[2]];
822 v4 = decode[src[3]];
823
824 *p++ = (v1 << 2 | v2 >> 4);
825 *p++ = (v2 << 4 | v3 >> 2);
826 *p++ = (v3 << 6 | v4);
827
828 src += 4;
829 }
830
831 if (pad > 0) {
832 v1 = decode[src[0]];
833 v2 = decode[src[1]];
834
835 *p++ = (v1 << 2 | v2 >> 4);
836
837 if (pad == 1) {
838 v3 = decode[src[2]];
839 *p++ = (v2 << 4 | v3 >> 2);
840 }
841 }
842
843 return (p - dst);
844 }
845