Rizin
unix-like reverse engineering framework and cli tools
punycode.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2017 Rakholiya Jenish
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_types.h>
5 #include <rz_util.h>
6 
7 #define BASE 36
8 #define TMIN 1
9 #define TMAX 26
10 #define SKEW 38
11 #define DAMP 700
12 #define INITIAL_N 128
13 #define INITIAL_BIAS 72
14 
16  int i = 0;
17  while (*(input + i)) {
18  i++;
19  }
20  return i;
21 }
22 
24  if (!input) {
25  eprintf("ERROR input is null\n");
26  return NULL;
27  }
28 
29  int i = 0;
30  int j = 0;
31  int len = utf32len(input);
32  ut8 *result = calloc(4, len + 1);
33  if (!result) {
34  eprintf("ERROR: out of memory\n");
35  return NULL;
36  }
37 
38  for (i = 0; i < len; i++) {
39  if (input[i] < 0x80) {
40  result[j] = input[i];
41  j++;
42  } else if (input[i] < 0x800) {
43  result[j + 1] = 0x80 | (input[i] & 0x3f);
44  result[j] = 0xc0 | ((input[i] >> 6) & 0x1f);
45  j += 2;
46  } else if (input[i] < 0x10000) {
47  result[j + 2] = 0x80 | (input[i] & 0x3f);
48  result[j + 1] = 0x80 | ((input[i] >> 6) & 0x3f);
49  result[j] = 0xe0 | ((input[i] >> 12) & 0xf);
50  j += 3;
51  } else if (input[i] < 0x200000) {
52  result[j + 3] = 0x80 | (input[i] & 0x3f);
53  result[j + 2] = 0x80 | ((input[i] >> 6) & 0x3f);
54  result[j + 1] = 0x80 | ((input[i] >> 12) & 0x3f);
55  result[j] = 0xf0 | ((input[i] >> 18) & 0x7);
56  j += 4;
57  } else {
58  eprintf("ERROR in toutf8. Seems like input is invalid\n");
59  free(result);
60  return NULL;
61  }
62  }
63 
64  result[j] = 0;
65  return result;
66 }
67 
68 ut32 *utf8toutf32(const ut8 *input, int len) {
69  if (!input) {
70  eprintf("ERROR input is null\n");
71  return NULL;
72  }
73 
74  int val = 0;
75  ut32 *result = calloc(len + 1, 4);
76 
77  if (!result) {
78  eprintf("ERROR: out of memory\n");
79  return NULL;
80  }
81 
82  for (int i = 0, j = 0; i < len; j++) {
83  if (input[i] >> 7 == 0) {
84  val = input[i];
85  i += 1;
86  } else if (input[i] >> 5 == 0x6 && (len - i) > 1) {
87  val = (((input[i] & 0x1f) << 6) & 0xfc0) |
88  (input[i + 1] & 0x3f);
89  i += 2;
90  } else if (input[i] >> 4 == 0xe && (len - i) > 2) {
91  val = (((input[i] & 0xf) << 12) & 0xf000) |
92  (((input[i + 1] & 0x3f) << 6) & 0xffc0) |
93  (input[i + 2] & 0x3f);
94  i += 3;
95  } else if (input[i] >> 3 == 0x1e && (len - i) > 3) {
96  val = (((input[i] & 0xf) << 18) & 0x1c0000) |
97  (((input[i + 1] & 0x3f) << 12) & 0x1ff000) |
98  (((input[i + 2] & 0x3f) << 6) & 0x1fffc0) |
99  (input[i + 3] & 0x3f);
100  i += 4;
101  } else {
102  eprintf("ERROR in toutf32. Seems like input is invalid.\n");
103  free(result);
104  return NULL;
105  }
106  result[j] = val;
107  }
108 
109  return result;
110 }
111 
112 ut32 adapt_bias(ut32 delta, unsigned n_points, int is_first) {
113  ut32 k = 0;
114  delta /= is_first ? DAMP : 2;
115  delta += delta / n_points;
116 
117  while (delta > ((BASE - TMIN) * TMAX) / 2) {
118  delta /= (BASE - TMIN);
119  k += BASE;
120  }
121 
122  return k + (((BASE - TMIN + 1) * delta) / (delta + SKEW));
123 }
124 
125 char encode_digit(int c) {
126  // assert (c >= 0 && c <= BASE - TMIN);
127  if (c > 25) {
128  return c + 22;
129  }
130  return c + 'a';
131 }
132 
133 static ut32 encode_var_int(const ut32 bias, const ut32 delta, char *dst) {
134  ut32 i, k, q, t;
135  i = 0;
136  k = BASE;
137  q = delta;
138 
139  while (true) {
140  if (k <= bias) {
141  t = TMIN;
142  } else if (k >= bias + TMAX) {
143  t = TMAX;
144  } else {
145  t = k - bias;
146  }
147 
148  if (q < t) {
149  break;
150  }
151 
152  dst[i++] = encode_digit(t + (q - t) % (BASE - t));
153 
154  q = (q - t) / (BASE - t);
155  k += BASE;
156  }
157 
158  dst[i++] = encode_digit(q);
159 
160  return i;
161 }
162 
164  if (IS_DIGIT(v)) {
165  return v - 22;
166  }
167  if (v >= 'a' && v <= 'z') {
168  return v - 'a';
169  }
170  if (v >= 'A' && v <= 'Z') {
171  return v - 'A';
172  }
173  return UT32_MAX;
174 }
175 
176 RZ_API char *rz_punycode_encode(const ut8 *src, int srclen, int *dstlen) {
177  ut32 m, n;
178  ut32 b, h;
179  ut32 si, di;
180  ut32 delta, bias;
181  ut32 *actualsrc = NULL;
182  ut32 len = 0;
183  char *dst = NULL;
184 
185  *dstlen = 0;
186 
187  if (!src || srclen < 1) {
188  return NULL;
189  }
190 
191  actualsrc = utf8toutf32(src, srclen);
192  if (!actualsrc) {
193  return NULL;
194  }
195 
196  len = utf32len(actualsrc);
197 
198  dst = calloc(2 * len + 10, 1);
199  if (!dst) {
200  free(actualsrc);
201  return NULL;
202  }
203 
204  for (si = 0, di = 0; si < len; si++) {
205  if (actualsrc[si] < 128) {
206  dst[di++] = actualsrc[si];
207  }
208  }
209 
210  b = h = di;
211 
212  if (di > 0) {
213  dst[di++] = '-';
214  }
215 
216  n = INITIAL_N;
217  bias = INITIAL_BIAS;
218 
219  for (delta = 0; h < len; n++, delta++) {
220  for (m = UT32_MAX, si = 0; si < len; si++) {
221  if (actualsrc[si] >= n && actualsrc[si] < m) {
222  m = actualsrc[si];
223  }
224  }
225 
226  if ((m - n) > (UT32_MAX - delta) / (h + 1)) {
227  free(actualsrc);
228  free(dst);
229  return NULL;
230  }
231 
232  delta += (m - n) * (h + 1);
233  n = m;
234 
235  for (si = 0; si < len; si++) {
236  if (actualsrc[si] < n) {
237  if (++delta == 0) {
238  free(actualsrc);
239  free(dst);
240  return NULL;
241  }
242  } else if (actualsrc[si] == n) {
243  di += encode_var_int(bias, delta, &dst[di]);
244  bias = adapt_bias(delta, h + 1, h == b);
245  delta = 0;
246  h++;
247  }
248  }
249  }
250  *dstlen = di;
251  free(actualsrc);
252  return dst;
253 }
254 
255 RZ_API char *rz_punycode_decode(const char *src, int srclen, int *dstlen) {
256  const char *p;
257  ut32 si, di;
258  ut32 b, n, t, i, k, w;
259  ut32 digit, org_i, bias;
260  ut32 *dst = NULL;
261  ut8 *finaldst = NULL;
262 
263  *dstlen = 0;
264  if (!src || srclen < 1) {
265  return NULL;
266  }
267 
268  dst = calloc(2 * srclen + 10, 4);
269  if (!dst) {
270  return NULL;
271  }
272 
273  for (si = 0; si < srclen; si++) {
274  if (src[si] & 0x80) {
275  free(dst);
276  return NULL; /*just return it*/
277  }
278  }
279 
280  for (p = src + srclen - 1; p > src && *p != '-'; p--) {
281  ;
282  }
283  b = p - src;
284 
285  di = b;
286  for (i = 0; i < di; i++) {
287  dst[i] = src[i];
288  }
289 
290  i = 0;
291  n = INITIAL_N;
292  bias = INITIAL_BIAS;
293 
294  for (si = b + (b > 0); si < srclen; di++) {
295  org_i = i;
296 
297  for (w = 1, k = BASE;; k += BASE) {
298  digit = decode_digit(src[si++]);
299 
300  if (digit == UT32_MAX) {
301  free(dst);
302  return NULL;
303  }
304 
305  if (digit > (UT32_MAX - i) / w) {
306  free(dst);
307  return NULL;
308  }
309 
310  i += digit * w;
311 
312  if (k <= bias) {
313  t = TMIN;
314  } else if (k >= bias + TMAX) {
315  t = TMAX;
316  } else {
317  t = k - bias;
318  }
319 
320  if (digit < t) {
321  break;
322  }
323 
324  if (w > UT32_MAX / (BASE - t)) {
325  free(dst);
326  return NULL;
327  }
328 
329  w *= BASE - t;
330  }
331 
332  bias = adapt_bias(i - org_i, di + 1, org_i == 0);
333 
334  if (i / (di + 1) > UT32_MAX - n) {
335  free(dst);
336  return NULL;
337  }
338 
339  n += i / (di + 1);
340  i %= (di + 1);
341 
342  memmove(dst + i + 1, dst + i, (di - i) * sizeof(ut32));
343  dst[i++] = n;
344  }
345 
346  finaldst = utf32toutf8(dst);
347  free(dst);
348  if (finaldst) {
349  *dstlen = strlen((const char *)finaldst);
350  } else {
351  eprintf("ERROR: finaldst is null\n");
352  return NULL;
353  }
354  return (char *)finaldst;
355 }
size_t len
Definition: 6502dis.c:15
si
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
ut16 val
Definition: armass64_const.h:6
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define w
Definition: crypto_rc6.c:13
uint32_t ut32
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
char * dst
Definition: lz4.h:724
int n
Definition: mipsasm.c:19
#define INITIAL_BIAS
Definition: punycode.c:13
RZ_API char * rz_punycode_encode(const ut8 *src, int srclen, int *dstlen)
Definition: punycode.c:176
char encode_digit(int c)
Definition: punycode.c:125
#define SKEW
Definition: punycode.c:10
ut32 adapt_bias(ut32 delta, unsigned n_points, int is_first)
Definition: punycode.c:112
#define DAMP
Definition: punycode.c:11
ut32 * utf8toutf32(const ut8 *input, int len)
Definition: punycode.c:68
static ut32 encode_var_int(const ut32 bias, const ut32 delta, char *dst)
Definition: punycode.c:133
#define INITIAL_N
Definition: punycode.c:12
#define BASE
Definition: punycode.c:7
int utf32len(ut32 *input)
Definition: punycode.c:15
RZ_API char * rz_punycode_decode(const char *src, int srclen, int *dstlen)
Definition: punycode.c:255
static ut32 decode_digit(ut32 v)
Definition: punycode.c:163
#define TMAX
Definition: punycode.c:9
#define TMIN
Definition: punycode.c:8
ut8 * utf32toutf8(ut32 *input)
Definition: punycode.c:23
#define eprintf(x, y...)
Definition: rlcc.c:7
#define IS_DIGIT(x)
Definition: rz_str_util.h:11
#define UT32_MAX
Definition: rz_types_base.h:99
#define b(i)
Definition: sha256.c:42
#define c(i)
Definition: sha256.c:43
#define h(i)
Definition: sha256.c:48
static st64 delta
Definition: vmenus.c:2425
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)