demangle-rust-v0.c 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042
  1. // SPDX-License-Identifier: Apache-2.0 OR MIT
  2. // The contents of this file come from the Rust rustc-demangle library, hosted
  3. // in the <https://github.com/rust-lang/rustc-demangle> repository, licensed
  4. // under "Apache-2.0 OR MIT". For copyright details, see
  5. // <https://github.com/rust-lang/rustc-demangle/blob/main/README.md>.
  6. // Please note that the file should be kept as close as possible to upstream.
  7. // Code for demangling Rust symbols. This code is mostly
  8. // a line-by-line translation of the Rust code in `rustc-demangle`.
  9. // you can find the latest version of this code in https://github.com/rust-lang/rustc-demangle
  10. #include <stdint.h>
  11. #include <stddef.h>
  12. #include <string.h>
  13. #include <stdbool.h>
  14. #include <sys/param.h>
  15. #include <stdio.h>
  16. #include "demangle-rust-v0.h"
  17. #if defined(__GNUC__) || defined(__clang__)
  18. #define NODISCARD __attribute__((warn_unused_result))
  19. #else
  20. #define NODISCARD
  21. #endif
  22. #define MAX_DEPTH 500
  23. typedef enum {
  24. DemangleOk,
  25. DemangleInvalid,
  26. DemangleRecursed,
  27. DemangleBug,
  28. } demangle_status;
  29. struct demangle_v0 {
  30. const char *mangled;
  31. size_t mangled_len;
  32. };
  33. struct demangle_legacy {
  34. const char *mangled;
  35. size_t mangled_len;
  36. size_t elements;
  37. };
  38. // private version of memrchr to avoid _GNU_SOURCE
  39. static void *demangle_memrchr(const void *s, int c, size_t n) {
  40. const uint8_t *s_ = s;
  41. for (; n != 0; n--) {
  42. if (s_[n-1] == c) {
  43. return (void*)&s_[n-1];
  44. }
  45. }
  46. return NULL;
  47. }
  48. static bool unicode_iscontrol(uint32_t ch) {
  49. // this is *technically* a unicode table, but
  50. // some unicode properties are simpler than you might think
  51. return ch < 0x20 || (ch >= 0x7f && ch < 0xa0);
  52. }
  53. // "good enough" tables, the only consequence is that when printing
  54. // *constant strings*, some characters are printed as `\u{abcd}` rather than themselves.
  55. //
  56. // I'm leaving these here to allow easily replacing them with actual
  57. // tables if desired.
  58. static bool unicode_isprint(uint32_t ch) {
  59. if (ch < 0x20) {
  60. return false;
  61. }
  62. if (ch < 0x7f) {
  63. return true;
  64. }
  65. return false;
  66. }
  67. static bool unicode_isgraphemextend(uint32_t ch) {
  68. (void)ch;
  69. return false;
  70. }
  71. static bool str_isascii(const char *s, size_t s_len) {
  72. for (size_t i = 0; i < s_len; i++) {
  73. if (s[i] & 0x80) {
  74. return false;
  75. }
  76. }
  77. return true;
  78. }
  79. typedef enum {
  80. PunycodeOk,
  81. PunycodeError
  82. } punycode_status;
  83. struct parser {
  84. // the parser assumes that `sym` has a safe "terminating byte". It might be NUL,
  85. // but it might also be something else if a symbol is "truncated".
  86. const char *sym;
  87. size_t sym_len;
  88. size_t next;
  89. uint32_t depth;
  90. };
  91. struct printer {
  92. demangle_status status; // if status == 0 parser is valid
  93. struct parser parser;
  94. char *out; // NULL for no output [in which case out_len is not decremented]
  95. size_t out_len;
  96. uint32_t bound_lifetime_depth;
  97. bool alternate;
  98. };
  99. static NODISCARD overflow_status printer_print_path(struct printer *printer, bool in_value);
  100. static NODISCARD overflow_status printer_print_type(struct printer *printer);
  101. static NODISCARD overflow_status printer_print_const(struct printer *printer, bool in_value);
  102. static NODISCARD demangle_status try_parse_path(struct parser *parser) {
  103. struct printer printer = {
  104. DemangleOk,
  105. *parser,
  106. NULL,
  107. SIZE_MAX,
  108. 0,
  109. false
  110. };
  111. overflow_status ignore = printer_print_path(&printer, false); // can't fail since no output
  112. (void)ignore;
  113. *parser = printer.parser;
  114. return printer.status;
  115. }
  116. NODISCARD static demangle_status rust_demangle_v0_demangle(const char *s, size_t s_len, struct demangle_v0 *res, const char **rest) {
  117. if (s_len > strlen(s)) {
  118. // s_len only exists to shorten the string, this is not a buffer API
  119. return DemangleInvalid;
  120. }
  121. const char *inner;
  122. size_t inner_len;
  123. if (s_len >= 2 && !strncmp(s, "_R", strlen("_R"))) {
  124. inner = s+2;
  125. inner_len = s_len - 2;
  126. } else if (s_len >= 1 && !strncmp(s, "R", strlen("R"))) {
  127. // On Windows, dbghelp strips leading underscores, so we accept "R..."
  128. // form too.
  129. inner = s+1;
  130. inner_len = s_len - 1;
  131. } else if (s_len >= 3 && !strncmp(s, "__R", strlen("__R"))) {
  132. // On OSX, symbols are prefixed with an extra _
  133. inner = s+3;
  134. inner_len = s_len - 3;
  135. } else {
  136. return DemangleInvalid;
  137. }
  138. // Paths always start with uppercase characters.
  139. if (*inner < 'A' || *inner > 'Z') {
  140. return DemangleInvalid;
  141. }
  142. if (!str_isascii(inner, inner_len)) {
  143. return DemangleInvalid;
  144. }
  145. struct parser parser = { inner, inner_len, 0, 0 };
  146. demangle_status status = try_parse_path(&parser);
  147. if (status != DemangleOk) return status;
  148. char next = parser.sym[parser.next];
  149. // Instantiating crate (paths always start with uppercase characters).
  150. if (parser.next < parser.sym_len && next >= 'A' && next <= 'Z') {
  151. status = try_parse_path(&parser);
  152. if (status != DemangleOk) return status;
  153. }
  154. res->mangled = inner;
  155. res->mangled_len = inner_len;
  156. if (rest) {
  157. *rest = parser.sym + parser.next;
  158. }
  159. return DemangleOk;
  160. }
  161. // This might require `len` to be up to 3 characters bigger than the real output len in case of utf-8
  162. NODISCARD static overflow_status rust_demangle_v0_display_demangle(struct demangle_v0 res, char *out, size_t len, bool alternate) {
  163. struct printer printer = {
  164. DemangleOk,
  165. {
  166. res.mangled,
  167. res.mangled_len,
  168. 0,
  169. 0
  170. },
  171. out,
  172. len,
  173. 0,
  174. alternate
  175. };
  176. if (printer_print_path(&printer, true) == OverflowOverflow) {
  177. return OverflowOverflow;
  178. }
  179. if (printer.out_len < OVERFLOW_MARGIN) {
  180. return OverflowOverflow;
  181. }
  182. *printer.out = '\0';
  183. return OverflowOk;
  184. }
  185. static size_t code_to_utf8(unsigned char *buffer, uint32_t code)
  186. {
  187. if (code <= 0x7F) {
  188. buffer[0] = code;
  189. return 1;
  190. }
  191. if (code <= 0x7FF) {
  192. buffer[0] = 0xC0 | (code >> 6); /* 110xxxxx */
  193. buffer[1] = 0x80 | (code & 0x3F); /* 10xxxxxx */
  194. return 2;
  195. }
  196. if (code <= 0xFFFF) {
  197. buffer[0] = 0xE0 | (code >> 12); /* 1110xxxx */
  198. buffer[1] = 0x80 | ((code >> 6) & 0x3F); /* 10xxxxxx */
  199. buffer[2] = 0x80 | (code & 0x3F); /* 10xxxxxx */
  200. return 3;
  201. }
  202. if (code <= 0x10FFFF) {
  203. buffer[0] = 0xF0 | (code >> 18); /* 11110xxx */
  204. buffer[1] = 0x80 | ((code >> 12) & 0x3F); /* 10xxxxxx */
  205. buffer[2] = 0x80 | ((code >> 6) & 0x3F); /* 10xxxxxx */
  206. buffer[3] = 0x80 | (code & 0x3F); /* 10xxxxxx */
  207. return 4;
  208. }
  209. return 0;
  210. }
  211. // return length of char at byte, or SIZE_MAX if invalid. buf should have 4 valid characters
  212. static NODISCARD size_t utf8_next_char(uint8_t *s, uint32_t *ch) {
  213. uint8_t byte = *s;
  214. // UTF8-1 = %x00-7F
  215. // UTF8-2 = %xC2-DF UTF8-tail
  216. // UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
  217. // %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
  218. // UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
  219. // %xF4 %x80-8F 2( UTF8-tail )
  220. if (byte < 0x80) {
  221. *ch = byte;
  222. return 1;
  223. } else if (byte < 0xc2) {
  224. return SIZE_MAX;
  225. } else if (byte < 0xe0) {
  226. if (s[1] >= 0x80 && s[1] < 0xc0) {
  227. *ch = ((byte&0x1f)<<6) + (s[1] & 0x3f);
  228. return 2;
  229. }
  230. return SIZE_MAX;
  231. } if (byte < 0xf0) {
  232. if (!(s[1] >= 0x80 && s[1] < 0xc0) || !(s[2] >= 0x80 && s[2] < 0xc0)) {
  233. return SIZE_MAX; // basic validation
  234. }
  235. if (byte == 0xe0 && s[1] < 0xa0) {
  236. return SIZE_MAX; // overshort
  237. }
  238. if (byte == 0xed && s[1] >= 0xa0) {
  239. return SIZE_MAX; // surrogate
  240. }
  241. *ch = ((byte&0x0f)<<12) + ((s[1] & 0x3f)<<6) + (s[2] & 0x3f);
  242. return 3;
  243. } else if (byte < 0xf5) {
  244. if (!(s[1] >= 0x80 && s[1] < 0xc0) || !(s[2] >= 0x80 && s[2] < 0xc0) || !(s[3] >= 0x80 && s[3] < 0xc0)) {
  245. return SIZE_MAX; // basic validation
  246. }
  247. if (byte == 0xf0 && s[1] < 0x90) {
  248. return SIZE_MAX; // overshort
  249. }
  250. if (byte == 0xf4 && s[1] >= 0x90) {
  251. return SIZE_MAX; // over max
  252. }
  253. *ch = ((byte&0x07)<<18) + ((s[1] & 0x3f)<<12) + ((s[2] & 0x3f)<<6) + (s[3]&0x3f);
  254. return 4;
  255. } else {
  256. return SIZE_MAX;
  257. }
  258. }
  259. static NODISCARD bool validate_char(uint32_t n) {
  260. return ((n ^ 0xd800) - 0x800) < 0x110000 - 0x800;
  261. }
  262. #define SMALL_PUNYCODE_LEN 128
  263. static NODISCARD punycode_status punycode_decode(const char *start, size_t ascii_len, const char *punycode_start, size_t punycode_len, uint32_t (*out_)[SMALL_PUNYCODE_LEN], size_t *out_len) {
  264. uint32_t *out = *out_;
  265. if (punycode_len == 0) {
  266. return PunycodeError;
  267. }
  268. if (ascii_len > SMALL_PUNYCODE_LEN) {
  269. return PunycodeError;
  270. }
  271. for (size_t i = 0; i < ascii_len; i++) {
  272. out[i] = start[i];
  273. }
  274. size_t len = ascii_len;
  275. size_t base = 36, t_min = 1, t_max = 26, skew = 38, damp = 700, bias = 72, i = 0, n = 0x80;
  276. for (;;) {
  277. size_t delta = 0, w = 1, k = 0;
  278. for (;;) {
  279. k += base;
  280. size_t biased = k < bias ? 0 : k - bias;
  281. size_t t = MIN(MAX(biased, t_min), t_max);
  282. size_t d;
  283. if (punycode_len == 0) {
  284. return PunycodeError;
  285. }
  286. char nx = *punycode_start++;
  287. punycode_len--;
  288. if ('a' <= nx && nx <= 'z') {
  289. d = nx - 'a';
  290. } else if ('0' <= nx && nx <= '9') {
  291. d = 26 + (nx - '0');
  292. } else {
  293. return PunycodeError;
  294. }
  295. if (w == 0 || d > SIZE_MAX / w || d*w > SIZE_MAX - delta) {
  296. return PunycodeError;
  297. }
  298. delta += d * w;
  299. if (d < t) {
  300. break;
  301. }
  302. if (base < t || w == 0 || (base - t) > SIZE_MAX / w) {
  303. return PunycodeError;
  304. }
  305. w *= (base - t);
  306. }
  307. len += 1;
  308. if (i > SIZE_MAX - delta) {
  309. return PunycodeError;
  310. }
  311. i += delta;
  312. if (n > SIZE_MAX - i / len) {
  313. return PunycodeError;
  314. }
  315. n += i / len;
  316. i %= len;
  317. // char validation
  318. if (n > UINT32_MAX || !validate_char((uint32_t)n)) {
  319. return PunycodeError;
  320. }
  321. // insert new character
  322. if (len > SMALL_PUNYCODE_LEN) {
  323. return PunycodeError;
  324. }
  325. memmove(out + i + 1, out + i, (len - i - 1) * sizeof(uint32_t));
  326. out[i] = (uint32_t)n;
  327. // start i index at incremented position
  328. i++;
  329. // If there are no more deltas, decoding is complete.
  330. if (punycode_len == 0) {
  331. *out_len = len;
  332. return PunycodeOk;
  333. }
  334. // Perform bias adaptation.
  335. delta /= damp;
  336. damp = 2;
  337. delta += delta / len;
  338. k = 0;
  339. while (delta > ((base - t_min) * t_max) / 2) {
  340. delta /= base - t_min;
  341. k += base;
  342. }
  343. bias = k + ((base - t_min + 1) * delta) / (delta + skew);
  344. }
  345. }
  346. struct ident {
  347. const char *ascii_start;
  348. size_t ascii_len;
  349. const char *punycode_start;
  350. size_t punycode_len;
  351. };
  352. static NODISCARD overflow_status display_ident(const char *ascii_start, size_t ascii_len, const char *punycode_start, size_t punycode_len, uint8_t *out, size_t *out_len) {
  353. uint32_t outbuf[SMALL_PUNYCODE_LEN];
  354. size_t wide_len;
  355. size_t out_buflen = *out_len;
  356. if (punycode_len == 0) {
  357. if (ascii_len > out_buflen) {
  358. return OverflowOverflow;
  359. }
  360. memcpy(out, ascii_start, ascii_len);
  361. *out_len = ascii_len;
  362. } else if (punycode_decode(ascii_start, ascii_len, punycode_start, punycode_len, &outbuf, &wide_len) == PunycodeOk) {
  363. size_t narrow_len = 0;
  364. for (size_t i = 0; i < wide_len; i++) {
  365. if (out_buflen - narrow_len < 4) {
  366. return OverflowOverflow;
  367. }
  368. unsigned char *pos = &out[narrow_len];
  369. narrow_len += code_to_utf8(pos, outbuf[i]);
  370. }
  371. *out_len = narrow_len;
  372. } else {
  373. size_t narrow_len = 0;
  374. if (out_buflen < strlen("punycode{")) {
  375. return OverflowOverflow;
  376. }
  377. memcpy(out, "punycode{", strlen("punycode{"));
  378. narrow_len = strlen("punycode{");
  379. if (ascii_len > 0) {
  380. if (out_buflen - narrow_len < ascii_len || out_buflen - narrow_len - ascii_len < 1) {
  381. return OverflowOverflow;
  382. }
  383. memcpy(out + narrow_len, ascii_start, ascii_len);
  384. narrow_len += ascii_len;
  385. out[narrow_len] = '-';
  386. narrow_len++;
  387. }
  388. if (out_buflen - narrow_len < punycode_len || out_buflen - narrow_len - punycode_len < 1) {
  389. return OverflowOverflow;
  390. }
  391. memcpy(out + narrow_len, punycode_start, punycode_len);
  392. narrow_len += punycode_len;
  393. out[narrow_len] = '}';
  394. narrow_len++;
  395. *out_len = narrow_len;
  396. }
  397. return OverflowOk;
  398. }
  399. static NODISCARD bool try_parse_uint(const char *buf, size_t len, uint64_t *result) {
  400. size_t cur = 0;
  401. for(;cur < len && buf[cur] == '0';cur++);
  402. uint64_t result_val = 0;
  403. if (len - cur > 16) return false;
  404. for(;cur < len;cur++) {
  405. char c = buf[cur];
  406. result_val <<= 4;
  407. if ('0' <= c && c <= '9') {
  408. result_val += c - '0';
  409. } else if ('a' <= c && c <= 'f') {
  410. result_val += 10 + (c - 'a');
  411. } else {
  412. return false;
  413. }
  414. }
  415. *result = result_val;
  416. return true;
  417. }
  418. static NODISCARD bool dinibble2int(const char *buf, uint8_t *result) {
  419. uint8_t result_val = 0;
  420. for (int i = 0; i < 2; i++) {
  421. char c = buf[i];
  422. result_val <<= 4;
  423. if ('0' <= c && c <= '9') {
  424. result_val += c - '0';
  425. } else if ('a' <= c && c <= 'f') {
  426. result_val += 10 + (c - 'a');
  427. } else {
  428. return false;
  429. }
  430. }
  431. *result = result_val;
  432. return true;
  433. }
  434. typedef enum {
  435. NtsOk = 0,
  436. NtsOverflow = 1,
  437. NtsInvalid = 2
  438. } nibbles_to_string_status;
  439. // '\u{10ffff}', +margin
  440. #define ESCAPED_SIZE 12
  441. static NODISCARD size_t char_to_string(uint32_t ch, uint8_t quote, bool first, char (*buf)[ESCAPED_SIZE]) {
  442. // encode the character
  443. char *escaped_buf = *buf;
  444. escaped_buf[0] = '\\';
  445. size_t escaped_len = 2;
  446. switch (ch) {
  447. case '\0':
  448. escaped_buf[1] = '0';
  449. break;
  450. case '\t':
  451. escaped_buf[1] = 't';
  452. break;
  453. case '\r':
  454. escaped_buf[1] = 'r';
  455. break;
  456. case '\n':
  457. escaped_buf[1] = 'n';
  458. break;
  459. case '\\':
  460. escaped_buf[1] = '\\';
  461. break;
  462. default:
  463. if (ch == quote) {
  464. escaped_buf[1] = ch;
  465. } else if (!unicode_isprint(ch) || (first && unicode_isgraphemextend(ch))) {
  466. int hexlen = snprintf(escaped_buf, ESCAPED_SIZE, "\\u{%x}", (unsigned int)ch);
  467. if (hexlen < 0) {
  468. return 0; // (snprintf shouldn't fail!)
  469. }
  470. escaped_len = hexlen;
  471. } else {
  472. // printable character
  473. escaped_buf[0] = ch;
  474. escaped_len = 1;
  475. }
  476. break;
  477. }
  478. return escaped_len;
  479. }
  480. // convert nibbles to a single/double-quoted string
  481. static NODISCARD nibbles_to_string_status nibbles_to_string(const char *buf, size_t len, uint8_t *out, size_t *out_len) {
  482. uint8_t quote = '"';
  483. bool first = true;
  484. if ((len % 2) != 0) {
  485. return NtsInvalid; // odd number of nibbles
  486. }
  487. size_t cur_out_len = 0;
  488. // write starting quote
  489. if (out != NULL) {
  490. cur_out_len = *out_len;
  491. if (cur_out_len == 0) {
  492. return NtsOverflow;
  493. }
  494. *out++ = quote;
  495. cur_out_len--;
  496. }
  497. uint8_t conv_buf[4] = {0};
  498. size_t conv_buf_len = 0;
  499. while (len > 1 || conv_buf_len > 0) {
  500. while (len > 1 && conv_buf_len < sizeof(conv_buf)) {
  501. if (!dinibble2int(buf, &conv_buf[conv_buf_len])) {
  502. return NtsInvalid;
  503. }
  504. conv_buf_len++;
  505. buf += 2;
  506. len -= 2;
  507. }
  508. // conv_buf is full here if possible, process 1 UTF-8 character
  509. uint32_t ch = 0;
  510. size_t consumed = utf8_next_char(conv_buf, &ch);
  511. if (consumed > conv_buf_len) {
  512. // either SIZE_MAX (invalid UTF-8) or finished input buffer and
  513. // there are still bytes remaining, in both cases invalid
  514. return NtsInvalid;
  515. }
  516. // "consume" the character
  517. memmove(conv_buf, conv_buf+consumed, conv_buf_len-consumed);
  518. conv_buf_len -= consumed;
  519. char escaped_buf[ESCAPED_SIZE];
  520. size_t escaped_len = char_to_string(ch, '"', first, &escaped_buf);
  521. if (out != NULL) {
  522. if (cur_out_len < escaped_len) {
  523. return NtsOverflow;
  524. }
  525. memcpy(out, escaped_buf, escaped_len);
  526. out += escaped_len;
  527. cur_out_len -= escaped_len;
  528. }
  529. first = false;
  530. }
  531. // write ending quote
  532. if (out != NULL) {
  533. if (cur_out_len == 0) {
  534. return NtsOverflow;
  535. }
  536. *out++ = quote;
  537. cur_out_len--;
  538. *out_len -= cur_out_len; // subtract remaining space to get used space
  539. }
  540. return NtsOk;
  541. }
  542. static const char* basic_type(uint8_t tag) {
  543. switch(tag) {
  544. case 'b':
  545. return "bool";
  546. case 'c':
  547. return "char";
  548. case 'e':
  549. return "str";
  550. case 'u':
  551. return "()";
  552. case 'a':
  553. return "i8";
  554. case 's':
  555. return "i16";
  556. case 'l':
  557. return "i32";
  558. case 'x':
  559. return "i64";
  560. case 'n':
  561. return "i128";
  562. case 'i':
  563. return "isize";
  564. case 'h':
  565. return "u8";
  566. case 't':
  567. return "u16";
  568. case 'm':
  569. return "u32";
  570. case 'y':
  571. return "u64";
  572. case 'o':
  573. return "u128";
  574. case 'j':
  575. return "usize";
  576. case 'f':
  577. return "f32";
  578. case 'd':
  579. return "f64";
  580. case 'z':
  581. return "!";
  582. case 'p':
  583. return "_";
  584. case 'v':
  585. return "...";
  586. default:
  587. return NULL;
  588. }
  589. }
  590. static NODISCARD demangle_status parser_push_depth(struct parser *parser) {
  591. parser->depth++;
  592. if (parser->depth > MAX_DEPTH) {
  593. return DemangleRecursed;
  594. } else {
  595. return DemangleOk;
  596. }
  597. }
  598. static demangle_status parser_pop_depth(struct parser *parser) {
  599. parser->depth--;
  600. return DemangleOk;
  601. }
  602. static uint8_t parser_peek(struct parser const *parser) {
  603. if (parser->next == parser->sym_len) {
  604. return 0; // add a "pseudo nul terminator" to avoid peeking past the end of a symbol
  605. } else {
  606. return parser->sym[parser->next];
  607. }
  608. }
  609. static bool parser_eat(struct parser *parser, uint8_t ch) {
  610. if (parser_peek(parser) == ch) {
  611. if (ch != 0) { // safety: make sure we don't skip past the NUL terminator
  612. parser->next++;
  613. }
  614. return true;
  615. } else {
  616. return false;
  617. }
  618. }
  619. static uint8_t parser_next(struct parser *parser) {
  620. // don't advance after end of input, and return an imaginary NUL terminator
  621. if (parser->next == parser->sym_len) {
  622. return 0;
  623. } else {
  624. return parser->sym[parser->next++];
  625. }
  626. }
  627. static NODISCARD demangle_status parser_ch(struct parser *parser, uint8_t *next) {
  628. // don't advance after end of input
  629. if (parser->next == parser->sym_len) {
  630. return DemangleInvalid;
  631. } else {
  632. *next = parser->sym[parser->next++];
  633. return DemangleOk;
  634. }
  635. }
  636. struct buf {
  637. const char *start;
  638. size_t len;
  639. };
  640. static NODISCARD demangle_status parser_hex_nibbles(struct parser *parser, struct buf *buf) {
  641. size_t start = parser->next;
  642. for (;;) {
  643. uint8_t ch = parser_next(parser);
  644. if (ch == '_') {
  645. break;
  646. }
  647. if (!(('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f'))) {
  648. return DemangleInvalid;
  649. }
  650. }
  651. buf->start = parser->sym + start;
  652. buf->len = parser->next - start - 1; // skip final _
  653. return DemangleOk;
  654. }
  655. static NODISCARD demangle_status parser_digit_10(struct parser *parser, uint8_t *out) {
  656. uint8_t ch = parser_peek(parser);
  657. if ('0' <= ch && ch <= '9') {
  658. *out = ch - '0';
  659. parser->next++;
  660. return DemangleOk;
  661. } else {
  662. return DemangleInvalid;
  663. }
  664. }
  665. static NODISCARD demangle_status parser_digit_62(struct parser *parser, uint64_t *out) {
  666. uint8_t ch = parser_peek(parser);
  667. if ('0' <= ch && ch <= '9') {
  668. *out = ch - '0';
  669. parser->next++;
  670. return DemangleOk;
  671. } else if ('a' <= ch && ch <= 'z') {
  672. *out = 10 + (ch - 'a');
  673. parser->next++;
  674. return DemangleOk;
  675. } else if ('A' <= ch && ch <= 'Z') {
  676. *out = 10 + 26 + (ch - 'A');
  677. parser->next++;
  678. return DemangleOk;
  679. } else {
  680. return DemangleInvalid;
  681. }
  682. }
  683. static NODISCARD demangle_status parser_integer_62(struct parser *parser, uint64_t *out) {
  684. if (parser_eat(parser, '_')) {
  685. *out = 0;
  686. return DemangleOk;
  687. }
  688. uint64_t x = 0;
  689. demangle_status status;
  690. while (!parser_eat(parser, '_')) {
  691. uint64_t d;
  692. if ((status = parser_digit_62(parser, &d)) != DemangleOk) {
  693. return status;
  694. }
  695. if (x > UINT64_MAX / 62) {
  696. return DemangleInvalid;
  697. }
  698. x *= 62;
  699. if (x > UINT64_MAX - d) {
  700. return DemangleInvalid;
  701. }
  702. x += d;
  703. }
  704. if (x == UINT64_MAX) {
  705. return DemangleInvalid;
  706. }
  707. *out = x + 1;
  708. return DemangleOk;
  709. }
  710. static NODISCARD demangle_status parser_opt_integer_62(struct parser *parser, uint8_t tag, uint64_t *out) {
  711. if (!parser_eat(parser, tag)) {
  712. *out = 0;
  713. return DemangleOk;
  714. }
  715. demangle_status status;
  716. if ((status = parser_integer_62(parser, out)) != DemangleOk) {
  717. return status;
  718. }
  719. if (*out == UINT64_MAX) {
  720. return DemangleInvalid;
  721. }
  722. *out = *out + 1;
  723. return DemangleOk;
  724. }
  725. static NODISCARD demangle_status parser_disambiguator(struct parser *parser, uint64_t *out) {
  726. return parser_opt_integer_62(parser, 's', out);
  727. }
  728. typedef uint8_t parser_namespace_type;
  729. static NODISCARD demangle_status parser_namespace(struct parser *parser, parser_namespace_type *out) {
  730. uint8_t next = parser_next(parser);
  731. if ('A' <= next && next <= 'Z') {
  732. *out = next;
  733. return DemangleOk;
  734. } else if ('a' <= next && next <= 'z') {
  735. *out = 0;
  736. return DemangleOk;
  737. } else {
  738. return DemangleInvalid;
  739. }
  740. }
  741. static NODISCARD demangle_status parser_backref(struct parser *parser, struct parser *out) {
  742. size_t start = parser->next;
  743. if (start == 0) {
  744. return DemangleBug;
  745. }
  746. size_t s_start = start - 1;
  747. uint64_t i;
  748. demangle_status status = parser_integer_62(parser, &i);
  749. if (status != DemangleOk) {
  750. return status;
  751. }
  752. if (i >= s_start) {
  753. return DemangleInvalid;
  754. }
  755. struct parser res = {
  756. .sym = parser->sym,
  757. .sym_len = parser->sym_len,
  758. .next = (size_t)i,
  759. .depth = parser->depth
  760. };
  761. status = parser_push_depth(&res);
  762. if (status != DemangleOk) {
  763. return status;
  764. }
  765. *out = res;
  766. return DemangleOk;
  767. }
  768. static NODISCARD demangle_status parser_ident(struct parser *parser, struct ident *out) {
  769. bool is_punycode = parser_eat(parser, 'u');
  770. size_t len;
  771. uint8_t d;
  772. demangle_status status = parser_digit_10(parser, &d);
  773. len = d;
  774. if (status != DemangleOk) {
  775. return status;
  776. }
  777. if (len) {
  778. for (;;) {
  779. status = parser_digit_10(parser, &d);
  780. if (status != DemangleOk) {
  781. break;
  782. }
  783. if (len > SIZE_MAX / 10) {
  784. return DemangleInvalid;
  785. }
  786. len *= 10;
  787. if (len > SIZE_MAX - d) {
  788. return DemangleInvalid;
  789. }
  790. len += d;
  791. }
  792. }
  793. // Skip past the optional `_` separator.
  794. parser_eat(parser, '_');
  795. size_t start = parser->next;
  796. if (parser->sym_len - parser->next < len) {
  797. return DemangleInvalid;
  798. }
  799. parser->next += len;
  800. const char *ident = &parser->sym[start];
  801. if (is_punycode) {
  802. const char *underscore = demangle_memrchr(ident, '_', (size_t)len);
  803. if (underscore == NULL) {
  804. *out = (struct ident){
  805. .ascii_start="",
  806. .ascii_len=0,
  807. .punycode_start=ident,
  808. .punycode_len=len
  809. };
  810. } else {
  811. size_t ascii_len = underscore - ident;
  812. // ascii_len <= len - 1 since `_` is in the first len bytes
  813. size_t punycode_len = len - 1 - ascii_len;
  814. *out = (struct ident){
  815. .ascii_start=ident,
  816. .ascii_len=ascii_len,
  817. .punycode_start=underscore + 1,
  818. .punycode_len=punycode_len
  819. };
  820. }
  821. if (out->punycode_len == 0) {
  822. return DemangleInvalid;
  823. }
  824. return DemangleOk;
  825. } else {
  826. *out = (struct ident) {
  827. .ascii_start=ident,
  828. .ascii_len=(size_t)len,
  829. .punycode_start="",
  830. .punycode_len=0,
  831. };
  832. return DemangleOk;
  833. }
  834. }
  835. #define INVALID_SYNTAX "{invalid syntax}"
  836. static const char *demangle_error_message(demangle_status status) {
  837. switch (status) {
  838. case DemangleInvalid:
  839. return INVALID_SYNTAX;
  840. case DemangleBug:
  841. return "{bug}";
  842. case DemangleRecursed:
  843. return "{recursion limit reached}";
  844. default:
  845. return "{unknown error}";
  846. }
  847. }
  848. #define PRINT(print_fn) \
  849. do { \
  850. if ((print_fn) == OverflowOverflow) { \
  851. return OverflowOverflow; \
  852. } \
  853. } while(0)
  854. #define PRINT_CH(printer, s) PRINT(printer_print_ch((printer), (s)))
  855. #define PRINT_STR(printer, s) PRINT(printer_print_str((printer), (s)))
  856. #define PRINT_U64(printer, s) PRINT(printer_print_u64((printer), (s)))
  857. #define PRINT_IDENT(printer, s) PRINT(printer_print_ident((printer), (s)))
  858. #define INVALID(printer) \
  859. do { \
  860. PRINT_STR((printer), INVALID_SYNTAX); \
  861. (printer)->status = DemangleInvalid; \
  862. return OverflowOk; \
  863. } while(0)
  864. #define PARSE(printer, method, ...) \
  865. do { \
  866. if ((printer)->status != DemangleOk) { \
  867. PRINT_STR((printer), "?"); \
  868. return OverflowOk; \
  869. } else { \
  870. demangle_status _parse_status = method(&(printer)->parser, ## __VA_ARGS__); \
  871. if (_parse_status != DemangleOk) { \
  872. PRINT_STR((printer), demangle_error_message(_parse_status)); \
  873. (printer)->status = _parse_status; \
  874. return OverflowOk; \
  875. } \
  876. } \
  877. } while(0)
  878. #define PRINT_SEP_LIST(printer, body, sep) \
  879. do { \
  880. size_t _sep_list_i; \
  881. PRINT_SEP_LIST_COUNT(printer, _sep_list_i, body, sep); \
  882. } while(0)
  883. #define PRINT_SEP_LIST_COUNT(printer, count, body, sep) \
  884. do { \
  885. count = 0; \
  886. while ((printer)->status == DemangleOk && !printer_eat((printer), 'E')) { \
  887. if (count > 0) { PRINT_STR(printer, sep); } \
  888. body; \
  889. count++; \
  890. } \
  891. } while(0)
  892. static bool printer_eat(struct printer *printer, uint8_t b) {
  893. if (printer->status != DemangleOk) {
  894. return false;
  895. }
  896. return parser_eat(&printer->parser, b);
  897. }
  898. static void printer_pop_depth(struct printer *printer) {
  899. if (printer->status == DemangleOk) {
  900. parser_pop_depth(&printer->parser);
  901. }
  902. }
  903. static NODISCARD overflow_status printer_print_buf(struct printer *printer, const char *start, size_t len) {
  904. if (printer->out == NULL) {
  905. return OverflowOk;
  906. }
  907. if (printer->out_len < len) {
  908. return OverflowOverflow;
  909. }
  910. memcpy(printer->out, start, len);
  911. printer->out += len;
  912. printer->out_len -= len;
  913. return OverflowOk;
  914. }
  915. static NODISCARD overflow_status printer_print_str(struct printer *printer, const char *buf) {
  916. return printer_print_buf(printer, buf, strlen(buf));
  917. }
  918. static NODISCARD overflow_status printer_print_ch(struct printer *printer, char ch) {
  919. return printer_print_buf(printer, &ch, 1);
  920. }
  921. static NODISCARD overflow_status printer_print_u64(struct printer *printer, uint64_t n) {
  922. char buf[32] = {0};
  923. sprintf(buf, "%llu", (unsigned long long)n); // printing uint64 uses 21 < 32 chars
  924. return printer_print_str(printer, buf);
  925. }
  926. static NODISCARD overflow_status printer_print_ident(struct printer *printer, struct ident *ident) {
  927. if (printer->out == NULL) {
  928. return OverflowOk;
  929. }
  930. size_t out_len = printer->out_len;
  931. overflow_status status;
  932. if ((status = display_ident(ident->ascii_start, ident->ascii_len, ident->punycode_start, ident->punycode_len, (uint8_t*)printer->out, &out_len)) != OverflowOk) {
  933. return status;
  934. }
  935. printer->out += out_len;
  936. printer->out_len -= out_len;
  937. return OverflowOk;
  938. }
  939. typedef overflow_status (*printer_fn)(struct printer *printer);
  940. typedef overflow_status (*backref_fn)(struct printer *printer, bool *arg);
  941. static NODISCARD overflow_status printer_print_backref(struct printer *printer, backref_fn func, bool *arg) {
  942. struct parser backref;
  943. PARSE(printer, parser_backref, &backref);
  944. if (printer->out == NULL) {
  945. return OverflowOk;
  946. }
  947. struct parser orig_parser = printer->parser;
  948. demangle_status orig_status = printer->status; // fixme not sure this is needed match for Ok on the Rust side
  949. printer->parser = backref;
  950. printer->status = DemangleOk;
  951. overflow_status status = func(printer, arg);
  952. printer->parser = orig_parser;
  953. printer->status = orig_status;
  954. return status;
  955. }
  956. static NODISCARD overflow_status printer_print_lifetime_from_index(struct printer *printer, uint64_t lt) {
  957. // Bound lifetimes aren't tracked when skipping printing.
  958. if (printer->out == NULL) {
  959. return OverflowOk;
  960. }
  961. PRINT_STR(printer, "'");
  962. if (lt == 0) {
  963. PRINT_STR(printer, "_");
  964. return OverflowOk;
  965. }
  966. if (printer->bound_lifetime_depth < lt) {
  967. INVALID(printer);
  968. } else {
  969. uint64_t depth = printer->bound_lifetime_depth - lt;
  970. if (depth < 26) {
  971. PRINT_CH(printer, 'a' + depth);
  972. } else {
  973. PRINT_STR(printer, "_");
  974. PRINT_U64(printer, depth);
  975. }
  976. return OverflowOk;
  977. }
  978. }
  979. static NODISCARD overflow_status printer_in_binder(struct printer *printer, printer_fn func) {
  980. uint64_t bound_lifetimes;
  981. PARSE(printer, parser_opt_integer_62, 'G', &bound_lifetimes);
  982. // Don't track bound lifetimes when skipping printing.
  983. if (printer->out == NULL) {
  984. return func(printer);
  985. }
  986. if (bound_lifetimes > 0) {
  987. PRINT_STR(printer, "for<");
  988. for (uint64_t i = 0; i < bound_lifetimes; i++) {
  989. if (i > 0) {
  990. PRINT_STR(printer, ", ");
  991. }
  992. printer->bound_lifetime_depth++;
  993. PRINT(printer_print_lifetime_from_index(printer, 1));
  994. }
  995. PRINT_STR(printer, "> ");
  996. }
  997. overflow_status r = func(printer);
  998. printer->bound_lifetime_depth -= bound_lifetimes;
  999. return r;
  1000. }
  1001. static NODISCARD overflow_status printer_print_generic_arg(struct printer *printer) {
  1002. if (printer_eat(printer, 'L')) {
  1003. uint64_t lt;
  1004. PARSE(printer, parser_integer_62, &lt);
  1005. return printer_print_lifetime_from_index(printer, lt);
  1006. } else if (printer_eat(printer, 'K')) {
  1007. return printer_print_const(printer, false);
  1008. } else {
  1009. return printer_print_type(printer);
  1010. }
  1011. }
  1012. static NODISCARD overflow_status printer_print_generic_args(struct printer *printer) {
  1013. PRINT_STR(printer, "<");
  1014. PRINT_SEP_LIST(printer, PRINT(printer_print_generic_arg(printer)), ", ");
  1015. PRINT_STR(printer, ">");
  1016. return OverflowOk;
  1017. }
  1018. static NODISCARD overflow_status printer_print_path_out_of_value(struct printer *printer, bool *_arg) {
  1019. (void)_arg;
  1020. return printer_print_path(printer, false);
  1021. }
  1022. static NODISCARD overflow_status printer_print_path_in_value(struct printer *printer, bool *_arg) {
  1023. (void)_arg;
  1024. return printer_print_path(printer, true);
  1025. }
  1026. static NODISCARD overflow_status printer_print_path(struct printer *printer, bool in_value) {
  1027. PARSE(printer, parser_push_depth);
  1028. uint8_t tag;
  1029. PARSE(printer, parser_ch, &tag);
  1030. overflow_status st;
  1031. uint64_t dis;
  1032. struct ident name;
  1033. parser_namespace_type ns;
  1034. char *orig_out;
  1035. switch(tag) {
  1036. case 'C':
  1037. PARSE(printer, parser_disambiguator, &dis);
  1038. PARSE(printer, parser_ident, &name);
  1039. PRINT_IDENT(printer, &name);
  1040. if (printer->out != NULL && !printer->alternate && dis != 0) {
  1041. PRINT_STR(printer, "[");
  1042. char buf[24] = {0};
  1043. sprintf(buf, "%llx", (unsigned long long)dis);
  1044. PRINT_STR(printer, buf);
  1045. PRINT_STR(printer, "]");
  1046. }
  1047. break;
  1048. case 'N':
  1049. PARSE(printer, parser_namespace, &ns);
  1050. if ((st = printer_print_path(printer, in_value)) != OverflowOk) {
  1051. return st;
  1052. }
  1053. // HACK(eddyb) if the parser is already marked as having errored,
  1054. // `parse!` below will print a `?` without its preceding `::`
  1055. // (because printing the `::` is skipped in certain conditions,
  1056. // i.e. a lowercase namespace with an empty identifier),
  1057. // so in order to get `::?`, the `::` has to be printed here.
  1058. if (printer->status != DemangleOk) {
  1059. PRINT_STR(printer, "::");
  1060. }
  1061. PARSE(printer, parser_disambiguator, &dis);
  1062. PARSE(printer, parser_ident, &name);
  1063. // Special namespace, like closures and shims
  1064. if (ns) {
  1065. PRINT_STR(printer, "::{");
  1066. if (ns == 'C') {
  1067. PRINT_STR(printer, "closure");
  1068. } else if (ns == 'S') {
  1069. PRINT_STR(printer, "shim");
  1070. } else {
  1071. PRINT_CH(printer, ns);
  1072. }
  1073. if (name.ascii_len != 0 || name.punycode_len != 0) {
  1074. PRINT_STR(printer, ":");
  1075. PRINT_IDENT(printer, &name);
  1076. }
  1077. PRINT_STR(printer, "#");
  1078. PRINT_U64(printer, dis);
  1079. PRINT_STR(printer, "}");
  1080. } else {
  1081. // Implementation-specific/unspecified namespaces
  1082. if (name.ascii_len != 0 || name.punycode_len != 0) {
  1083. PRINT_STR(printer, "::");
  1084. PRINT_IDENT(printer, &name);
  1085. }
  1086. }
  1087. break;
  1088. case 'M':
  1089. case 'X':
  1090. // for impls, ignore the impls own path
  1091. PARSE(printer, parser_disambiguator, &dis);
  1092. orig_out = printer->out;
  1093. printer->out = NULL;
  1094. PRINT(printer_print_path(printer, false));
  1095. printer->out = orig_out;
  1096. // fallthru
  1097. case 'Y':
  1098. PRINT_STR(printer, "<");
  1099. PRINT(printer_print_type(printer));
  1100. if (tag != 'M') {
  1101. PRINT_STR(printer, " as ");
  1102. PRINT(printer_print_path(printer, false));
  1103. }
  1104. PRINT_STR(printer, ">");
  1105. break;
  1106. case 'I':
  1107. PRINT(printer_print_path(printer, in_value));
  1108. if (in_value) {
  1109. PRINT_STR(printer, "::");
  1110. }
  1111. PRINT(printer_print_generic_args(printer));
  1112. break;
  1113. case 'B':
  1114. PRINT(printer_print_backref(printer, in_value ? printer_print_path_in_value : printer_print_path_out_of_value, NULL));
  1115. break;
  1116. default:
  1117. INVALID(printer);
  1118. break;
  1119. }
  1120. printer_pop_depth(printer);
  1121. return OverflowOk;
  1122. }
  1123. static NODISCARD overflow_status printer_print_const_uint(struct printer *printer, uint8_t tag) {
  1124. struct buf hex;
  1125. PARSE(printer, parser_hex_nibbles, &hex);
  1126. uint64_t val;
  1127. if (try_parse_uint(hex.start, hex.len, &val)) {
  1128. PRINT_U64(printer, val);
  1129. } else {
  1130. PRINT_STR(printer, "0x");
  1131. PRINT(printer_print_buf(printer, hex.start, hex.len));
  1132. }
  1133. if (printer->out != NULL && !printer->alternate) {
  1134. const char *ty = basic_type(tag);
  1135. if (/* safety */ ty != NULL) {
  1136. PRINT_STR(printer, ty);
  1137. }
  1138. }
  1139. return OverflowOk;
  1140. }
  1141. static NODISCARD overflow_status printer_print_const_str_literal(struct printer *printer) {
  1142. struct buf hex;
  1143. PARSE(printer, parser_hex_nibbles, &hex);
  1144. size_t out_len = SIZE_MAX;
  1145. nibbles_to_string_status nts_status = nibbles_to_string(hex.start, hex.len, NULL, &out_len);
  1146. switch (nts_status) {
  1147. case NtsOk:
  1148. if (printer->out != NULL) {
  1149. out_len = printer->out_len;
  1150. nts_status = nibbles_to_string(hex.start, hex.len, (uint8_t*)printer->out, &out_len);
  1151. if (nts_status != NtsOk) {
  1152. return OverflowOverflow;
  1153. }
  1154. printer->out += out_len;
  1155. printer->out_len -= out_len;
  1156. }
  1157. return OverflowOk;
  1158. case NtsOverflow:
  1159. // technically if there is a string of size `SIZE_MAX/6` whose escaped version overflows
  1160. // SIZE_MAX but has an invalid char, this will be a "fake" overflow. In practice,
  1161. // that is not going to happen and a fuzzer will not generate strings of this length.
  1162. return OverflowOverflow;
  1163. case NtsInvalid:
  1164. default:
  1165. INVALID(printer);
  1166. }
  1167. }
  1168. static NODISCARD overflow_status printer_print_const_struct(struct printer *printer) {
  1169. uint64_t dis;
  1170. struct ident name;
  1171. PARSE(printer, parser_disambiguator, &dis);
  1172. PARSE(printer, parser_ident, &name);
  1173. PRINT_IDENT(printer, &name);
  1174. PRINT_STR(printer, ": ");
  1175. return printer_print_const(printer, true);
  1176. }
  1177. static NODISCARD overflow_status printer_print_const_out_of_value(struct printer *printer, bool *_arg) {
  1178. (void)_arg;
  1179. return printer_print_const(printer, false);
  1180. }
  1181. static NODISCARD overflow_status printer_print_const_in_value(struct printer *printer, bool *_arg) {
  1182. (void)_arg;
  1183. return printer_print_const(printer, true);
  1184. }
  1185. static NODISCARD overflow_status printer_print_const(struct printer *printer, bool in_value) {
  1186. uint8_t tag;
  1187. PARSE(printer, parser_ch, &tag);
  1188. PARSE(printer, parser_push_depth);
  1189. struct buf hex;
  1190. uint64_t val;
  1191. size_t count;
  1192. bool opened_brace = false;
  1193. #define OPEN_BRACE_IF_OUTSIDE_EXPR \
  1194. do { if (!in_value) { \
  1195. opened_brace = true; \
  1196. PRINT_STR(printer, "{"); \
  1197. } } while(0)
  1198. switch(tag) {
  1199. case 'p':
  1200. PRINT_STR(printer, "_");
  1201. break;
  1202. // Primitive leaves with hex-encoded values (see `basic_type`).
  1203. case 'a':
  1204. case 's':
  1205. case 'l':
  1206. case 'x':
  1207. case 'n':
  1208. case 'i':
  1209. if (printer_eat(printer, 'n')) {
  1210. PRINT_STR(printer, "-");
  1211. }
  1212. /* fallthrough */
  1213. case 'h':
  1214. case 't':
  1215. case 'm':
  1216. case 'y':
  1217. case 'o':
  1218. case 'j':
  1219. PRINT(printer_print_const_uint(printer, tag));
  1220. break;
  1221. case 'b':
  1222. PARSE(printer, parser_hex_nibbles, &hex);
  1223. if (try_parse_uint(hex.start, hex.len, &val)) {
  1224. if (val == 0) {
  1225. PRINT_STR(printer, "false");
  1226. } else if (val == 1) {
  1227. PRINT_STR(printer, "true");
  1228. } else {
  1229. INVALID(printer);
  1230. }
  1231. } else {
  1232. INVALID(printer);
  1233. }
  1234. break;
  1235. case 'c':
  1236. PARSE(printer, parser_hex_nibbles, &hex);
  1237. if (try_parse_uint(hex.start, hex.len, &val)
  1238. && val < UINT32_MAX
  1239. && validate_char((uint32_t)val))
  1240. {
  1241. char escaped_buf[ESCAPED_SIZE];
  1242. size_t escaped_size = char_to_string((uint32_t)val, '\'', true, &escaped_buf);
  1243. PRINT_STR(printer, "'");
  1244. PRINT(printer_print_buf(printer, escaped_buf, escaped_size));
  1245. PRINT_STR(printer, "'");
  1246. } else {
  1247. INVALID(printer);
  1248. }
  1249. break;
  1250. case 'e':
  1251. OPEN_BRACE_IF_OUTSIDE_EXPR;
  1252. PRINT_STR(printer, "*");
  1253. PRINT(printer_print_const_str_literal(printer));
  1254. break;
  1255. case 'R':
  1256. case 'Q':
  1257. if (tag == 'R' && printer_eat(printer, 'e')) {
  1258. PRINT(printer_print_const_str_literal(printer));
  1259. } else {
  1260. OPEN_BRACE_IF_OUTSIDE_EXPR;
  1261. PRINT_STR(printer, "&");
  1262. if (tag != 'R') {
  1263. PRINT_STR(printer, "mut ");
  1264. }
  1265. PRINT(printer_print_const(printer, true));
  1266. }
  1267. break;
  1268. case 'A':
  1269. OPEN_BRACE_IF_OUTSIDE_EXPR;
  1270. PRINT_STR(printer, "[");
  1271. PRINT_SEP_LIST(printer, PRINT(printer_print_const(printer, true)), ", ");
  1272. PRINT_STR(printer, "]");
  1273. break;
  1274. case 'T':
  1275. OPEN_BRACE_IF_OUTSIDE_EXPR;
  1276. PRINT_STR(printer, "(");
  1277. PRINT_SEP_LIST_COUNT(printer, count, PRINT(printer_print_const(printer, true)), ", ");
  1278. if (count == 1) {
  1279. PRINT_STR(printer, ",");
  1280. }
  1281. PRINT_STR(printer, ")");
  1282. break;
  1283. case 'V':
  1284. OPEN_BRACE_IF_OUTSIDE_EXPR;
  1285. PRINT(printer_print_path(printer, true));
  1286. PARSE(printer, parser_ch, &tag);
  1287. switch(tag) {
  1288. case 'U':
  1289. break;
  1290. case 'T':
  1291. PRINT_STR(printer, "(");
  1292. PRINT_SEP_LIST(printer, PRINT(printer_print_const(printer, true)), ", ");
  1293. PRINT_STR(printer, ")");
  1294. break;
  1295. case 'S':
  1296. PRINT_STR(printer, " { ");
  1297. PRINT_SEP_LIST(printer, PRINT(printer_print_const_struct(printer)), ", ");
  1298. PRINT_STR(printer, " }");
  1299. break;
  1300. default:
  1301. INVALID(printer);
  1302. }
  1303. break;
  1304. case 'B':
  1305. PRINT(printer_print_backref(printer, in_value ? printer_print_const_in_value : printer_print_const_out_of_value, NULL));
  1306. break;
  1307. default:
  1308. INVALID(printer);
  1309. }
  1310. #undef OPEN_BRACE_IF_OUTSIDE_EXPR
  1311. if (opened_brace) {
  1312. PRINT_STR(printer, "}");
  1313. }
  1314. printer_pop_depth(printer);
  1315. return OverflowOk;
  1316. }
  1317. /// A trait in a trait object may have some "existential projections"
  1318. /// (i.e. associated type bindings) after it, which should be printed
  1319. /// in the `<...>` of the trait, e.g. `dyn Trait<T, U, Assoc=X>`.
  1320. /// To this end, this method will keep the `<...>` of an 'I' path
  1321. /// open, by omitting the `>`, and return `Ok(true)` in that case.
  1322. static NODISCARD overflow_status printer_print_maybe_open_generics(struct printer *printer, bool *open) {
  1323. if (printer_eat(printer, 'B')) {
  1324. // NOTE(eddyb) the closure may not run if printing is being skipped,
  1325. // but in that case the returned boolean doesn't matter.
  1326. *open = false;
  1327. return printer_print_backref(printer, printer_print_maybe_open_generics, open);
  1328. } else if(printer_eat(printer, 'I')) {
  1329. PRINT(printer_print_path(printer, false));
  1330. PRINT_STR(printer, "<");
  1331. PRINT_SEP_LIST(printer, PRINT(printer_print_generic_arg(printer)), ", ");
  1332. *open = true;
  1333. return OverflowOk;
  1334. } else {
  1335. PRINT(printer_print_path(printer, false));
  1336. *open = false;
  1337. return OverflowOk;
  1338. }
  1339. }
  1340. static NODISCARD overflow_status printer_print_dyn_trait(struct printer *printer) {
  1341. bool open;
  1342. PRINT(printer_print_maybe_open_generics(printer, &open));
  1343. while (printer_eat(printer, 'p')) {
  1344. if (!open) {
  1345. PRINT_STR(printer, "<");
  1346. open = true;
  1347. } else {
  1348. PRINT_STR(printer, ", ");
  1349. }
  1350. struct ident name;
  1351. PARSE(printer, parser_ident, &name);
  1352. PRINT_IDENT(printer, &name);
  1353. PRINT_STR(printer, " = ");
  1354. PRINT(printer_print_type(printer));
  1355. }
  1356. if (open) {
  1357. PRINT_STR(printer, ">");
  1358. }
  1359. return OverflowOk;
  1360. }
  1361. static NODISCARD overflow_status printer_print_object_bounds(struct printer *printer) {
  1362. PRINT_SEP_LIST(printer, PRINT(printer_print_dyn_trait(printer)), " + ");
  1363. return OverflowOk;
  1364. }
  1365. static NODISCARD overflow_status printer_print_function_type(struct printer *printer) {
  1366. bool is_unsafe = printer_eat(printer, 'U');
  1367. const char *abi;
  1368. size_t abi_len;
  1369. if (printer_eat(printer, 'K')) {
  1370. if (printer_eat(printer, 'C')) {
  1371. abi = "C";
  1372. abi_len = 1;
  1373. } else {
  1374. struct ident abi_ident;
  1375. PARSE(printer, parser_ident, &abi_ident);
  1376. if (abi_ident.ascii_len == 0 || abi_ident.punycode_len != 0) {
  1377. INVALID(printer);
  1378. }
  1379. abi = abi_ident.ascii_start;
  1380. abi_len = abi_ident.ascii_len;
  1381. }
  1382. } else {
  1383. abi = NULL;
  1384. abi_len = 0;
  1385. }
  1386. if (is_unsafe) {
  1387. PRINT_STR(printer, "unsafe ");
  1388. }
  1389. if (abi != NULL) {
  1390. PRINT_STR(printer, "extern \"");
  1391. // replace _ with -
  1392. while (abi_len > 0) {
  1393. const char *minus = memchr(abi, '_', abi_len);
  1394. if (minus == NULL) {
  1395. PRINT(printer_print_buf(printer, (const char*)abi, abi_len));
  1396. break;
  1397. } else {
  1398. size_t space_to_minus = minus - abi;
  1399. PRINT(printer_print_buf(printer, (const char*)abi, space_to_minus));
  1400. PRINT_STR(printer, "-");
  1401. abi = minus + 1;
  1402. abi_len -= (space_to_minus + 1);
  1403. }
  1404. }
  1405. PRINT_STR(printer, "\" ");
  1406. }
  1407. PRINT_STR(printer, "fn(");
  1408. PRINT_SEP_LIST(printer, PRINT(printer_print_type(printer)), ", ");
  1409. PRINT_STR(printer, ")");
  1410. if (printer_eat(printer, 'u')) {
  1411. // Skip printing the return type if it's 'u', i.e. `()`.
  1412. } else {
  1413. PRINT_STR(printer, " -> ");
  1414. PRINT(printer_print_type(printer));
  1415. }
  1416. return OverflowOk;
  1417. }
  1418. static NODISCARD overflow_status printer_print_type_backref(struct printer *printer, bool *_arg) {
  1419. (void)_arg;
  1420. return printer_print_type(printer);
  1421. }
  1422. static NODISCARD overflow_status printer_print_type(struct printer *printer) {
  1423. uint8_t tag;
  1424. PARSE(printer, parser_ch, &tag);
  1425. const char *basic_ty = basic_type(tag);
  1426. if (basic_ty) {
  1427. return printer_print_str(printer, basic_ty);
  1428. }
  1429. uint64_t count;
  1430. uint64_t lt;
  1431. PARSE(printer, parser_push_depth);
  1432. switch (tag) {
  1433. case 'R':
  1434. case 'Q':
  1435. PRINT_STR(printer, "&");
  1436. if (printer_eat(printer, 'L')) {
  1437. PARSE(printer, parser_integer_62, &lt);
  1438. if (lt != 0) {
  1439. PRINT(printer_print_lifetime_from_index(printer, lt));
  1440. PRINT_STR(printer, " ");
  1441. }
  1442. }
  1443. if (tag != 'R') {
  1444. PRINT_STR(printer, "mut ");
  1445. }
  1446. PRINT(printer_print_type(printer));
  1447. break;
  1448. case 'P':
  1449. case 'O':
  1450. PRINT_STR(printer, "*");
  1451. if (tag != 'P') {
  1452. PRINT_STR(printer, "mut ");
  1453. } else {
  1454. PRINT_STR(printer, "const ");
  1455. }
  1456. PRINT(printer_print_type(printer));
  1457. break;
  1458. case 'A':
  1459. case 'S':
  1460. PRINT_STR(printer, "[");
  1461. PRINT(printer_print_type(printer));
  1462. if (tag == 'A') {
  1463. PRINT_STR(printer, "; ");
  1464. PRINT(printer_print_const(printer, true));
  1465. }
  1466. PRINT_STR(printer, "]");
  1467. break;
  1468. case 'T':
  1469. PRINT_STR(printer, "(");
  1470. PRINT_SEP_LIST_COUNT(printer, count, PRINT(printer_print_type(printer)), ", ");
  1471. if (count == 1) {
  1472. PRINT_STR(printer, ",");
  1473. }
  1474. PRINT_STR(printer, ")");
  1475. break;
  1476. case 'F':
  1477. PRINT(printer_in_binder(printer, printer_print_function_type));
  1478. break;
  1479. case 'D':
  1480. PRINT_STR(printer, "dyn ");
  1481. PRINT(printer_in_binder(printer, printer_print_object_bounds));
  1482. if (!printer_eat(printer, 'L')) {
  1483. INVALID(printer);
  1484. }
  1485. PARSE(printer, parser_integer_62, &lt);
  1486. if (lt != 0) {
  1487. PRINT_STR(printer, " + ");
  1488. PRINT(printer_print_lifetime_from_index(printer, lt));
  1489. }
  1490. break;
  1491. case 'B':
  1492. PRINT(printer_print_backref(printer, printer_print_type_backref, NULL));
  1493. break;
  1494. default:
  1495. // Go back to the tag, so `print_path` also sees it.
  1496. if (printer->status == DemangleOk && /* safety */ printer->parser.next > 0) {
  1497. printer->parser.next--;
  1498. }
  1499. PRINT(printer_print_path(printer, false));
  1500. }
  1501. printer_pop_depth(printer);
  1502. return OverflowOk;
  1503. }
  1504. NODISCARD static demangle_status rust_demangle_legacy_demangle(const char *s, size_t s_len, struct demangle_legacy *res, const char **rest)
  1505. {
  1506. if (s_len > strlen(s)) {
  1507. // s_len only exists to shorten the string, this is not a buffer API
  1508. return DemangleInvalid;
  1509. }
  1510. const char *inner;
  1511. size_t inner_len;
  1512. if (s_len >= 3 && !strncmp(s, "_ZN", 3)) {
  1513. inner = s + 3;
  1514. inner_len = s_len - 3;
  1515. } else if (s_len >= 2 && !strncmp(s, "ZN", 2)) {
  1516. // On Windows, dbghelp strips leading underscores, so we accept "ZN...E"
  1517. // form too.
  1518. inner = s + 2;
  1519. inner_len = s_len - 2;
  1520. } else if (s_len >= 4 && !strncmp(s, "__ZN", 4)) {
  1521. // On OSX, symbols are prefixed with an extra _
  1522. inner = s + 4;
  1523. inner_len = s_len - 4;
  1524. } else {
  1525. return DemangleInvalid;
  1526. }
  1527. if (!str_isascii(inner, inner_len)) {
  1528. return DemangleInvalid;
  1529. }
  1530. size_t elements = 0;
  1531. const char *chars = inner;
  1532. size_t chars_len = inner_len;
  1533. if (chars_len == 0) {
  1534. return DemangleInvalid;
  1535. }
  1536. char c;
  1537. while ((c = *chars) != 'E') {
  1538. // Decode an identifier element's length
  1539. if (c < '0' || c > '9') {
  1540. return DemangleInvalid;
  1541. }
  1542. size_t len = 0;
  1543. while (c >= '0' && c <= '9') {
  1544. size_t d = c - '0';
  1545. if (len > SIZE_MAX / 10) {
  1546. return DemangleInvalid;
  1547. }
  1548. len *= 10;
  1549. if (len > SIZE_MAX - d) {
  1550. return DemangleInvalid;
  1551. }
  1552. len += d;
  1553. chars++;
  1554. chars_len--;
  1555. if (chars_len == 0) {
  1556. return DemangleInvalid;
  1557. }
  1558. c = *chars;
  1559. }
  1560. // Advance by the length
  1561. if (chars_len <= len) {
  1562. return DemangleInvalid;
  1563. }
  1564. chars += len;
  1565. chars_len -= len;
  1566. elements++;
  1567. }
  1568. *res = (struct demangle_legacy) { inner, inner_len, elements };
  1569. *rest = chars + 1;
  1570. return DemangleOk;
  1571. }
  1572. static bool is_rust_hash(const char *s, size_t len) {
  1573. if (len == 0 || s[0] != 'h') {
  1574. return false;
  1575. }
  1576. for (size_t i = 1; i < len; i++) {
  1577. if (!((s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f') || (s[i] >= 'A' && s[i] <= 'F'))) {
  1578. return false;
  1579. }
  1580. }
  1581. return true;
  1582. }
  1583. NODISCARD static overflow_status rust_demangle_legacy_display_demangle(struct demangle_legacy res, char *out, size_t len, bool alternate)
  1584. {
  1585. struct printer printer = {
  1586. // not actually using the parser part of the printer, just keeping it to share the format functions
  1587. DemangleOk,
  1588. { NULL },
  1589. out,
  1590. len,
  1591. 0,
  1592. alternate
  1593. };
  1594. const char *inner = res.mangled;
  1595. for (size_t element = 0; element < res.elements; element++) {
  1596. size_t i = 0;
  1597. const char *rest;
  1598. for (rest = inner; rest < res.mangled + res.mangled_len && *rest >= '0' && *rest <= '9'; rest++) {
  1599. i *= 10;
  1600. i += *rest - '0';
  1601. }
  1602. if ((size_t)(res.mangled + res.mangled_len - rest) < i) {
  1603. // safety: shouldn't reach this place if the input string is validated. bail out.
  1604. // safety: we knwo rest <= res.mangled + res.mangled_len from the for-loop above
  1605. break;
  1606. }
  1607. size_t len = i;
  1608. inner = rest + len;
  1609. // From here on, inner contains a pointer to the next element, rest[:len] to the current one
  1610. if (alternate && element + 1 == res.elements && is_rust_hash(rest, i)) {
  1611. break;
  1612. }
  1613. if (element != 0) {
  1614. PRINT_STR(&printer, "::");
  1615. }
  1616. if (len >= 2 && !strncmp(rest, "_$", 2)) {
  1617. rest++;
  1618. len--;
  1619. }
  1620. while (len > 0) {
  1621. if (rest[0] == '.') {
  1622. if (len >= 2 && rest[1] == '.') {
  1623. PRINT_STR(&printer, "::");
  1624. rest += 2;
  1625. len -= 2;
  1626. } else {
  1627. PRINT_STR(&printer, ".");
  1628. rest += 1;
  1629. len -= 1;
  1630. }
  1631. } else if (rest[0] == '$') {
  1632. const char *escape = memchr(rest + 1, '$', len - 1);
  1633. if (escape == NULL) {
  1634. break;
  1635. }
  1636. const char *escape_start = rest + 1;
  1637. size_t escape_len = escape - (rest + 1);
  1638. size_t next_len = len - (escape + 1 - rest);
  1639. const char *next_rest = escape + 1;
  1640. char ch;
  1641. if ((escape_len == 2 && escape_start[0] == 'S' && escape_start[1] == 'P')) {
  1642. ch = '@';
  1643. } else if ((escape_len == 2 && escape_start[0] == 'B' && escape_start[1] == 'P')) {
  1644. ch = '*';
  1645. } else if ((escape_len == 2 && escape_start[0] == 'R' && escape_start[1] == 'F')) {
  1646. ch = '&';
  1647. } else if ((escape_len == 2 && escape_start[0] == 'L' && escape_start[1] == 'T')) {
  1648. ch = '<';
  1649. } else if ((escape_len == 2 && escape_start[0] == 'G' && escape_start[1] == 'T')) {
  1650. ch = '>';
  1651. } else if ((escape_len == 2 && escape_start[0] == 'L' && escape_start[1] == 'P')) {
  1652. ch = '(';
  1653. } else if ((escape_len == 2 && escape_start[0] == 'R' && escape_start[1] == 'P')) {
  1654. ch = ')';
  1655. } else if ((escape_len == 1 && escape_start[0] == 'C')) {
  1656. ch = ',';
  1657. } else {
  1658. if (escape_len > 1 && escape_start[0] == 'u') {
  1659. escape_start++;
  1660. escape_len--;
  1661. uint64_t val;
  1662. if (try_parse_uint(escape_start, escape_len, &val)
  1663. && val < UINT32_MAX
  1664. && validate_char((uint32_t)val))
  1665. {
  1666. if (!unicode_iscontrol(val)) {
  1667. uint8_t wchr[4];
  1668. size_t wchr_len = code_to_utf8(wchr, (uint32_t)val);
  1669. PRINT(printer_print_buf(&printer, (const char*)wchr, wchr_len));
  1670. len = next_len;
  1671. rest = next_rest;
  1672. continue;
  1673. }
  1674. }
  1675. }
  1676. break; // print the rest of this element raw
  1677. }
  1678. PRINT_CH(&printer, ch);
  1679. len = next_len;
  1680. rest = next_rest;
  1681. } else {
  1682. size_t j = 0;
  1683. for (;j < len && rest[j] != '$' && rest[j] != '.';j++);
  1684. if (j == len) {
  1685. break;
  1686. }
  1687. PRINT(printer_print_buf(&printer, rest, j));
  1688. rest += j;
  1689. len -= j;
  1690. }
  1691. }
  1692. PRINT(printer_print_buf(&printer, rest, len));
  1693. }
  1694. if (printer.out_len < OVERFLOW_MARGIN) {
  1695. return OverflowOverflow;
  1696. }
  1697. *printer.out = '\0';
  1698. return OverflowOk;
  1699. }
  1700. static bool is_symbol_like(const char *s, size_t len) {
  1701. // rust-demangle definition of symbol like: control characters and space are not symbol-like, all else is
  1702. for (size_t i = 0; i < len; i++) {
  1703. char ch = s[i];
  1704. if (!(ch >= 0x21 && ch <= 0x7e)) {
  1705. return false;
  1706. }
  1707. }
  1708. return true;
  1709. }
  1710. void rust_demangle_demangle(const char *s, struct demangle *res)
  1711. {
  1712. // During ThinLTO LLVM may import and rename internal symbols, so strip out
  1713. // those endings first as they're one of the last manglings applied to symbol
  1714. // names.
  1715. const char *llvm = ".llvm.";
  1716. const char *found_llvm = strstr(s, llvm);
  1717. size_t s_len = strlen(s);
  1718. if (found_llvm) {
  1719. const char *all_hex_ptr = found_llvm + strlen(".llvm.");
  1720. bool all_hex = true;
  1721. for (;*all_hex_ptr;all_hex_ptr++) {
  1722. if (!(('0' <= *all_hex_ptr && *all_hex_ptr <= '9') ||
  1723. ('A' <= *all_hex_ptr && *all_hex_ptr <= 'F') ||
  1724. *all_hex_ptr == '@')) {
  1725. all_hex = false;
  1726. break;
  1727. }
  1728. }
  1729. if (all_hex) {
  1730. s_len = found_llvm - s;
  1731. }
  1732. }
  1733. const char *suffix;
  1734. struct demangle_legacy legacy;
  1735. demangle_status st = rust_demangle_legacy_demangle(s, s_len, &legacy, &suffix);
  1736. if (st == DemangleOk) {
  1737. *res = (struct demangle) {
  1738. .style=DemangleStyleLegacy,
  1739. .mangled=legacy.mangled,
  1740. .mangled_len=legacy.mangled_len,
  1741. .elements=legacy.elements,
  1742. .original=s,
  1743. .original_len=s_len,
  1744. .suffix=suffix,
  1745. .suffix_len=s_len - (suffix - s),
  1746. };
  1747. } else {
  1748. struct demangle_v0 v0;
  1749. st = rust_demangle_v0_demangle(s, s_len, &v0, &suffix);
  1750. if (st == DemangleOk) {
  1751. *res = (struct demangle) {
  1752. .style=DemangleStyleV0,
  1753. .mangled=v0.mangled,
  1754. .mangled_len=v0.mangled_len,
  1755. .elements=0,
  1756. .original=s,
  1757. .original_len=s_len,
  1758. .suffix=suffix,
  1759. .suffix_len=s_len - (suffix - s),
  1760. };
  1761. } else {
  1762. *res = (struct demangle) {
  1763. .style=DemangleStyleUnknown,
  1764. .mangled=NULL,
  1765. .mangled_len=0,
  1766. .elements=0,
  1767. .original=s,
  1768. .original_len=s_len,
  1769. .suffix=s,
  1770. .suffix_len=0,
  1771. };
  1772. }
  1773. }
  1774. // Output like LLVM IR adds extra period-delimited words. See if
  1775. // we are in that case and save the trailing words if so.
  1776. if (res->suffix_len) {
  1777. if (res->suffix[0] == '.' && is_symbol_like(res->suffix, res->suffix_len)) {
  1778. // Keep the suffix
  1779. } else {
  1780. // Reset the suffix and invalidate the demangling
  1781. res->style = DemangleStyleUnknown;
  1782. res->suffix_len = 0;
  1783. }
  1784. }
  1785. }
  1786. bool rust_demangle_is_known(struct demangle *res) {
  1787. return res->style != DemangleStyleUnknown;
  1788. }
  1789. overflow_status rust_demangle_display_demangle(struct demangle const *res, char *out, size_t len, bool alternate) {
  1790. size_t original_len = res->original_len;
  1791. size_t out_len;
  1792. switch (res->style) {
  1793. case DemangleStyleUnknown:
  1794. if (len < original_len) {
  1795. return OverflowOverflow;
  1796. } else {
  1797. memcpy(out, res->original, original_len);
  1798. out += original_len;
  1799. len -= original_len;
  1800. break;
  1801. }
  1802. break;
  1803. case DemangleStyleLegacy: {
  1804. struct demangle_legacy legacy = {
  1805. res->mangled,
  1806. res->mangled_len,
  1807. res->elements
  1808. };
  1809. if (rust_demangle_legacy_display_demangle(legacy, out, len, alternate) == OverflowOverflow) {
  1810. return OverflowOverflow;
  1811. }
  1812. out_len = strlen(out);
  1813. out += out_len;
  1814. len -= out_len;
  1815. break;
  1816. }
  1817. case DemangleStyleV0: {
  1818. struct demangle_v0 v0 = {
  1819. res->mangled,
  1820. res->mangled_len
  1821. };
  1822. if (rust_demangle_v0_display_demangle(v0, out, len, alternate) == OverflowOverflow) {
  1823. return OverflowOverflow;
  1824. }
  1825. out_len = strlen(out);
  1826. out += out_len;
  1827. len -= out_len;
  1828. break;
  1829. }
  1830. }
  1831. size_t suffix_len = res->suffix_len;
  1832. if (len < suffix_len || len - suffix_len < OVERFLOW_MARGIN) {
  1833. return OverflowOverflow;
  1834. }
  1835. memcpy(out, res->suffix, suffix_len);
  1836. out[suffix_len] = 0;
  1837. return OverflowOk;
  1838. }