1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2016 Tom Lane <tgl@sss.pgh.pa.us> 14 * Copyright 2017 Nexenta Systems, Inc. 15 */ 16 17 #include <err.h> 18 #include <errno.h> 19 #include <locale.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <time.h> 24 25 /* 26 * #6907: generate random UTF8 strings, strxfrm'ing them in process. 27 * Walk through comparing each string with all strings, and checking 28 * that strcoll() and strcmp() for strxfrm'ed data produce same results. 29 */ 30 #define NSTRINGS 2000 31 #define MAXSTRLEN 20 32 #define MAXXFRMLEN (MAXSTRLEN * 20) 33 34 typedef struct { 35 char sval[MAXSTRLEN]; 36 char xval[MAXXFRMLEN]; 37 } cstr; 38 39 int 40 main(void) 41 { 42 cstr data[NSTRINGS]; 43 char *curloc; 44 int i, j; 45 46 if ((curloc = setlocale(LC_ALL, "")) == NULL) 47 err(1, "setlocale"); 48 49 /* Ensure new random() values on every run */ 50 srandom((unsigned int) time(NULL)); 51 52 /* Generate random UTF8 strings of length less than MAXSTRLEN bytes */ 53 for (i = 0; i < NSTRINGS; i++) { 54 char *p; 55 int len; 56 57 again: 58 p = data[i].sval; 59 len = 1 + (random() % (MAXSTRLEN - 1)); 60 while (len > 0) { 61 int c; 62 63 /* 64 * Generate random printable char in ISO8859-1 range. 65 * Bias towards producing a lot of spaces. 66 */ 67 if ((random() % 16) < 3) { 68 c = ' '; 69 } else { 70 do { 71 c = random() & 0xFF; 72 } while (!((c >= ' ' && c <= 127) || 73 (c >= 0xA0 && c <= 0xFF))); 74 } 75 76 if (c <= 127) { 77 *p++ = c; 78 len--; 79 } else { 80 if (len < 2) 81 break; 82 /* Poor man's utf8-ification */ 83 *p++ = 0xC0 + (c >> 6); 84 len--; 85 *p++ = 0x80 + (c & 0x3F); 86 len--; 87 } 88 } 89 *p = '\0'; 90 91 /* strxfrm() each string as we produce it */ 92 errno = 0; 93 if (strxfrm(data[i].xval, data[i].sval, 94 MAXXFRMLEN) >= MAXXFRMLEN) { 95 errx(1, "strxfrm() result for %d-length string " 96 "exceeded %d bytes", (int)strlen(data[i].sval), 97 MAXXFRMLEN); 98 } 99 /* Amend strxfrm() failing for certain characters (#7962) */ 100 if (errno != 0) 101 goto again; 102 } 103 104 for (i = 0; i < NSTRINGS; i++) { 105 for (j = 0; j < NSTRINGS; j++) { 106 int sr = strcoll(data[i].sval, data[j].sval); 107 int sx = strcmp(data[i].xval, data[j].xval); 108 109 if ((sr * sx < 0) || (sr * sx == 0 && sr + sx != 0)) { 110 errx(1, "%s: diff for \"%s\" and \"%s\"", 111 curloc, data[i].sval, data[j].sval); 112 } 113 } 114 } 115 116 return (0); 117 } 118