222 {
223 strview_t sv;
224 strview_t name;
225 uint64_t len;
226 size_t rem;
227 boolean_t last = B_FALSE;
228
229 if (st->rds_error != 0 || sv_remaining(svp) == 0)
230 return (B_FALSE);
231
232 sv_init_sv(&sv, svp);
233
234 if (!rustdem_parse_num(st, &sv, &len)) {
235 DEMDEBUG("ERROR: no leading length");
236 st->rds_error = EINVAL;
237 return (B_FALSE);
238 }
239
240 rem = sv_remaining(&sv);
241
242 if (rem < len || len == SIZE_MAX) {
243 st->rds_error = EINVAL;
244 return (B_FALSE);
245 }
246
247 /* Is this the last segment before the terminating E? */
248 if (rem == len + 1) {
249 VERIFY3U(sv_peek(&sv, -1), ==, 'E');
250 last = B_TRUE;
251 }
252
253 if (!first && !rustdem_add_sep(st))
254 return (B_FALSE);
255
256 /* Reduce length of seg to the length we parsed */
257 (void) sv_init_sv_range(&name, &sv, len);
258
259 DEMDEBUG("%s: segment='%.*s'", __func__, SV_PRINT(&name));
260
261 /*
262 * A rust hash starts with 'h', and is the last component of a name
367 * uppercase digits are used, and other rust demanglers all
368 * seem to assume the hash must contain lower-case hex digits.
369 */
370 case '0': case '1': case '2': case '3':
371 case '4': case '5': case '6': case '7':
372 case '8': case '9': case 'a': case 'b':
373 case 'c': case 'd': case 'e': case 'f':
374 if (!rustdem_append_c(st, c))
375 return (B_FALSE);
376 break;
377 default:
378 return (B_FALSE);
379 }
380 }
381
382 sv_init_sv(svp, &sv);
383 return (B_TRUE);
384 }
385
386 /*
387 * A 10 digit value would imply a name 1Gb or larger in size. It seems
388 * unlikely to the point of absurdity any such value could every possibly
389 * be valid (or even have compiled properly). This also prevents the
390 * uint64_t conversion from possibly overflowing since the value must always
391 * be below 10 * UINT32_MAX.
392 */
393 #define MAX_DIGITS 10
394
395 static boolean_t
396 rustdem_parse_num(rustdem_state_t *restrict st, strview_t *restrict svp,
397 uint64_t *restrict valp)
398 {
399 strview_t snum;
400 uint64_t v = 0;
401 size_t ndigits = 0;
402 char c;
403
404 if (st->rds_error != 0)
405 return (B_FALSE);
406
407 sv_init_sv(&snum, svp);
408
409 DEMDEBUG("%s: str='%.*s'", __func__, SV_PRINT(&snum));
410
411 c = sv_peek(&snum, 0);
412 if (!ISDIGIT(c)) {
413 DEMDEBUG("%s: ERROR no digits in str\n", __func__);
|
222 {
223 strview_t sv;
224 strview_t name;
225 uint64_t len;
226 size_t rem;
227 boolean_t last = B_FALSE;
228
229 if (st->rds_error != 0 || sv_remaining(svp) == 0)
230 return (B_FALSE);
231
232 sv_init_sv(&sv, svp);
233
234 if (!rustdem_parse_num(st, &sv, &len)) {
235 DEMDEBUG("ERROR: no leading length");
236 st->rds_error = EINVAL;
237 return (B_FALSE);
238 }
239
240 rem = sv_remaining(&sv);
241
242 if (rem < len) {
243 st->rds_error = EINVAL;
244 return (B_FALSE);
245 }
246
247 /* Is this the last segment before the terminating E? */
248 if (rem == len + 1) {
249 VERIFY3U(sv_peek(&sv, -1), ==, 'E');
250 last = B_TRUE;
251 }
252
253 if (!first && !rustdem_add_sep(st))
254 return (B_FALSE);
255
256 /* Reduce length of seg to the length we parsed */
257 (void) sv_init_sv_range(&name, &sv, len);
258
259 DEMDEBUG("%s: segment='%.*s'", __func__, SV_PRINT(&name));
260
261 /*
262 * A rust hash starts with 'h', and is the last component of a name
367 * uppercase digits are used, and other rust demanglers all
368 * seem to assume the hash must contain lower-case hex digits.
369 */
370 case '0': case '1': case '2': case '3':
371 case '4': case '5': case '6': case '7':
372 case '8': case '9': case 'a': case 'b':
373 case 'c': case 'd': case 'e': case 'f':
374 if (!rustdem_append_c(st, c))
375 return (B_FALSE);
376 break;
377 default:
378 return (B_FALSE);
379 }
380 }
381
382 sv_init_sv(svp, &sv);
383 return (B_TRUE);
384 }
385
386 /*
387 * We have to pick an arbitrary limit here; 999,999,999 fits comfortably
388 * within an int32_t, so let's go with that, as it seems unlikely we'd
389 * ever see a larger value in context.
390 */
391 #define MAX_DIGITS 9
392
393 static boolean_t
394 rustdem_parse_num(rustdem_state_t *restrict st, strview_t *restrict svp,
395 uint64_t *restrict valp)
396 {
397 strview_t snum;
398 uint64_t v = 0;
399 size_t ndigits = 0;
400 char c;
401
402 if (st->rds_error != 0)
403 return (B_FALSE);
404
405 sv_init_sv(&snum, svp);
406
407 DEMDEBUG("%s: str='%.*s'", __func__, SV_PRINT(&snum));
408
409 c = sv_peek(&snum, 0);
410 if (!ISDIGIT(c)) {
411 DEMDEBUG("%s: ERROR no digits in str\n", __func__);
|