From a1be16530bd3feeb684ff5c190a3c64248c8189d Mon Sep 17 00:00:00 2001 From: messense Date: Fri, 4 Feb 2022 16:29:17 +0800 Subject: [PATCH] Fix String roundtrip with interior nul bytes --- .../src/bindgen_runtime/js_values/string.rs | 8 +++++--- examples/napi/__test__/typegen.spec.ts.md | 1 + examples/napi/__test__/typegen.spec.ts.snap | Bin 2512 -> 2519 bytes examples/napi/__test__/values.spec.ts | 5 +++++ examples/napi/index.d.ts | 1 + examples/napi/src/string.rs | 5 +++++ 6 files changed, 17 insertions(+), 3 deletions(-) diff --git a/crates/napi/src/bindgen_runtime/js_values/string.rs b/crates/napi/src/bindgen_runtime/js_values/string.rs index 9cb05176..2af44beb 100644 --- a/crates/napi/src/bindgen_runtime/js_values/string.rs +++ b/crates/napi/src/bindgen_runtime/js_values/string.rs @@ -2,7 +2,6 @@ use crate::{bindgen_prelude::*, check_status, sys, Error, Result, Status}; use std::ffi::{c_void, CStr}; use std::fmt::Display; -#[cfg(feature = "latin1")] use std::mem; use std::ops::Deref; use std::ptr; @@ -53,12 +52,15 @@ impl FromNapiValue for String { "Failed to convert napi `string` into rust type `String`" )?; - match unsafe { CStr::from_ptr(buf_ptr) }.to_str() { + let mut ret = mem::ManuallyDrop::new(ret); + let buf_ptr = ret.as_mut_ptr(); + let bytes = unsafe { Vec::from_raw_parts(buf_ptr as *mut u8, written_char_count, len) }; + match String::from_utf8(bytes) { Err(e) => Err(Error::new( Status::InvalidArg, format!("Failed to read utf8 string, {}", e), )), - Ok(s) => Ok(s.to_owned()), + Ok(s) => Ok(s), } } } diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index 96a2b1a6..5ff1e771 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -126,6 +126,7 @@ Generated by [AVA](https://avajs.dev). export function concatStr(s: string): string␊ export function concatUtf16(s: string): string␊ export function concatLatin1(s: string): string␊ + export function roundtripStr(s: string): string␊ export function setSymbolInObj(symbol: symbol): object␊ export function createSymbol(): symbol␊ export function withoutAbortController(a: number, b: number): Promise␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index 81724e3cbd418011b9014dca43141541124ef9d8..b3edb4fae0fd7734586c469a6acd499db8177487 100644 GIT binary patch literal 2519 zcmV;|2`KhKRzVDv%xDU~GlNhAi7zJF#roayJXF zu^EyhX(DQd;S6o7UIX1f=yP9+-7oAX^qd)z8i}Oj1ThR~F6TbyHp5^0ek6mD`sFvK zxsKTV-_%g1QAh?%u!L$x0+}Q%&_qvSMncvneI7Bc1dRbwt6zQ%L#pWyB>cm(KRv_0 z-~I8~pMQTvUcMk&MO^4s$QAV?Mqa#JfkkE(SDi&%rKy&yInR*z6Vh#;AFp0q8US`5 z%S4kPqDqm&d(9F-qci^_$n~nXOCDATNf-^Kh$iHlZ(3$yZYdS~Q_6^%jC~oI?d!L# zY#3j*9#|{MxyITTO>DU0mzM6w= z)C#EOi2@TMb!jYFf`ZX3bK~*XDVWtEYM~tA2Zwh3hJIgRL@KCS!6K=A%k)9nmmwOh(DzLnrt>nAABQC zn1b2$bH$R7t$tKeJij52RWX{!NZBTbNg@+hmalNw2?N>0i8{&_&~?4FwKX6NfltNc z`o_?JQ3;oEJ!HwH;eD2LP3U=C#Hn^9Dnhg-X;=Xc4XGTtz?q{`Bf(Y;QyBPCMvRIQ zdk9UI^l88dBrKEMZ_C^sYxr$1Qh+G5^qh3ohSovBok|%rSwiy z{lz5Ff5CSs5AiZ0 zpbLn_V(`UKe97-&xP!w(J{Y1F-{Pdp4V}LmWQGZ0W4+3+fNf76Z*6+4H7m@5YCBBiokdm+?aG99s`nhVyfvw)e}z0O8`OzXulqRFu42mw zHPILTf%}E>mG;u=f(bfi*d#oF8_6Pa9*bmjeN#fazaQ>wwe1)E6f_99Czb<8TxoEOw``(3Xi)PmwbV{mN5JCF7Ebg{BzkO$FFk64o z6VIRjl4XIgdg&UP0oQ#_r|;1>0%oV}n_Q!bRJpkE2t^yUOz958T7c-FjDQ3xpd zAjV7qUC$1HuXKN7=jq_@D0FEXPk~P)m>IU>CyJvWc+88;vA_gwUuW`Hn)-BZQ@+K- zQ_3EB=E3fuiI%Bu`>@&pJ0~)VpzW@yVapyVklIs7HHqQ_)9x7POEY-_eY{X&2TMam z`>eR}Irq%!i(hTKRHD_J_N0OT73dvNO`}s8vad|;i$#QhvArESg&mcXWsJ!p1M}0q z(+<{PKoCH>(pOuXrV+`z$SX*Q+0xPnyV))s%Rp#pHD>74bkYud#``Fe)M1`KajcLR zh>A&+o>y~bx1&slBUthm=W^MuL^=U##GYPtOi(J00UY>1u@6&p?jHa96YI$Q%nY8_SQJ{O`a2`IlKo@$QC_j`<8* zS0^hygv*RFAT3<#jXDk2rk2}xEMeva!8}X{Lz;kD@NF8e>BSVZ`;|KC1C`1U6xI}5u3Df#xQTR=D1c$2!K=ZU{c8w zfgZ@5-LMYA-QGwtrW2oa84LGX&MR9*yXG3TF{{D>uHdpvad zqm0zTR@&v6v#j7)$IyIgJg0hC6;>8MzYn?oKmF{Im9}ttdUASys(*%eQ@Kmher3r? zEd1;-&v`LTlr<;2@mX}I8ZG{=QpetWN%=gZ%!hrRppUX5TH*IjRCh~tu~i~rOK26O zhVnKq!2BzDg*O!#NKVCgX}!N6ZW+j#Cyw^J<2T*Y!*0(>1r-m7TR-h=*S#LvC;xs7u4Hyw8;=hmXZh;}DaL!6ezN#Lu*gxF7NX6d%tO;jzYc ho38C#g*NfwVadB-wN2kIeVBb*`9E4E;Zv_5005Z=!&LwP literal 2512 zcmV;>2`~0RRzVay8=_5`RKEt+S)m^9uvO z?#43KB#5X|h6&H6+&W0Ln)#O`R1FZ*_hi(1pkyUq9!9>M&|hH zZ8Ke7H%S+^9#$SelozBs;EKS13c3rWQG!eWv)(^AY+b(V{?tCb=r)N+Mm~!(h+ZNB z&7}bQ>F;G6DzDZgtvIHWS4ziR^mh!4H%u#{TWTT#Z%p+73}%!7oU>StxMHvNl3uS&CW=TWNu+uA zR(dqh64=&OQLytDoMVs1PPi`RokoIfRsFNP} zMiMgxtE=aV#UWe$sHAv)O&-c(G>eg$nBwm-_}xo@C9@iDIG9=!`fJVa?4rb%_*^CWdIIkY|XQj z-btcAn9am`O0ia7qj64>AFM*j4xt zFGB*lfLLq{ej1Vq0@cO@GJXzXhWnei zIFv~Y-&^>7!SCR68$Sux;7e`Zc_&2>FhrE`{ujdl<1%7k{R_Z+pXH7TioxjZcWs1l`G_feu< z#g-AOqc8jm&vWHV?WNT@6LiF|Nw^0$l6mAjh z$78f40G%`Fh{IP|MO)C5Wk|LyE5}=4H99^u#m<9R*mbf(p=vBRt4QD-IPwf$CCFt) zsnTDm?awT4)1NJ?9zE_$L4$yMVmWZcl?KOn%O=W$1~uza3+;4y1T5}s;YQy?(x=7< z_^^>Z(l;Arpvz5RI(2K(W7TntI;~u-D6-d?xw}bR=)a3P0sx_Xw&?at@>5!03LMdl zK&mK7sZY6zI?1>7?x=NPWN&4~VGk4KR1Q~Xh%y#J7D`fm!Cwpk_{{yKM1!6pF= z2@l^jF10#gDXBS8r`$351$xfdnXRkM=AwDZSu|%TE^q|^JA`tZlBkrgtGeKM?Ew{i zX6r9{;wf~aF%MbpyR+Nb&F$vrMMcch>nuvt#`?N9E04Z79Fr;S=R>;N-oKggwsog^Mga&t~JX}I{ zv;SGBWe!0@M>o7lXIXah&T$7T(|Ed`!OiPaF?&I&rd%jbLBA5P>B|YaIAGwE@U(d? zqYzN^L5!Ikx|$sTU+Uh*_T$0dQRvb(9s{o+7|ev_NMJ&?)0S-NQk|Y{3b&YO^>k=6 z4|WSpu}pN!hut>VEtXLPZFEIVS~he*YL6jRCyMt?`(mIk%;FLB@qvgPDGe3vvHS(+ zyc^3Oa+U2*fmV0gV+Q^gpm#_$jZS39zA(AZ77+r#_G;)9_N$ou#u)r5n4k2V_O1d0 zoEp-PzT9k>#vVtdJMvgQ>+> z0%iOm9fz1S{lV^jfVA}~;W)tn&w`eVMettJlK7Bv6F=fX9mz<1Pu_yRLSpF?J{kik zRu1BjN4S4n;h4m8c5Bxw?z7B{WLtudXq3Mp&4UusJhj^-&e7KQ^B~&sDGwhg0+{Gq*sQK)jNZ@4*iC;oNra7ekcC;j|K4 z=fW{WNn7E1#_YY!;Umqb5ioAhmWiDr&v&WjhmgI94q3zhjw;Xz`d_==vuo2&U5w-q zn|jTlb;bZScXr4j<*R6JOe@b;G3Yq^cJAeP zPTB3+@J{cp`m*aYfCb;_aPg6LlUPTrs zfJ!=qt-GC2HEheshC$8%AC|M(X!eqiRZA)SE$KC}A9F^thxa8H1C%`;I{i^fYGG^a z^2}J4aI9izemXp(dQcWt7C(F6xc)!=86_=k;q><8^gUEPR(DgmOVa*ol95>WGsZmU z#WYdYjO@mf=uS0S{5we%d-Kc4(~L47_E~~HOp9oV-#by=Db&SgfrKrgWsn-m+q?kt zQ|}UQ$}y0f8sj7M?ryMYAZJDvt#?OnIwuF6u9FH%27;SEZEsag18tN8&_?6iDUu26 z5=sEHn9zHa(<= diff --git a/examples/napi/__test__/values.spec.ts b/examples/napi/__test__/values.spec.ts index 3dc40f32..919e1367 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -11,6 +11,7 @@ import { concatLatin1, concatStr, concatUtf16, + roundtripStr, getNums, getWords, sumNums, @@ -106,6 +107,10 @@ test('string', (t) => { concatUtf16('JavaScript 🌳 你好 napi'), 'JavaScript 🌳 你好 napi + Rust 🦀 string!', ) + t.is( + roundtripStr('what up?!\u0000after the NULL'), + 'what up?!\u0000after the NULL', + ) }) test('array', (t) => { diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index 54b7eac8..7c0e8945 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -116,6 +116,7 @@ export function contains(source: string, target: string): boolean export function concatStr(s: string): string export function concatUtf16(s: string): string export function concatLatin1(s: string): string +export function roundtripStr(s: string): string export function setSymbolInObj(symbol: symbol): object export function createSymbol(): symbol export function withoutAbortController(a: number, b: number): Promise diff --git a/examples/napi/src/string.rs b/examples/napi/src/string.rs index ee2e49df..f14f0e94 100644 --- a/examples/napi/src/string.rs +++ b/examples/napi/src/string.rs @@ -20,3 +20,8 @@ fn concat_utf16(s: Utf16String) -> Utf16String { fn concat_latin1(s: Latin1String) -> String { format!("{} + Rust 🦀 string!", s) } + +#[napi] +pub fn roundtrip_str(s: String) -> String { + s +}