From 3894db5e421d5a41732015c027bc0c418fc68e3c Mon Sep 17 00:00:00 2001 From: LongYinan Date: Mon, 8 Sep 2025 13:45:17 +0800 Subject: [PATCH] fix(napi): JsStringUtf8 memory leak (#2911) --- crates/napi/src/js_values/string/mod.rs | 12 ++++++------ crates/napi/src/js_values/string/utf8.rs | 9 +++++---- .../__tests__/__snapshots__/values.spec.ts.md | 2 ++ .../__snapshots__/values.spec.ts.snap | Bin 8329 -> 8337 bytes examples/napi/__tests__/values.spec.ts | 2 ++ examples/napi/example.wasi-browser.js | 1 + examples/napi/example.wasi.cjs | 1 + examples/napi/index.cjs | 1 + examples/napi/index.d.cts | 2 ++ examples/napi/src/string.rs | 7 ++++++- 10 files changed, 26 insertions(+), 11 deletions(-) diff --git a/crates/napi/src/js_values/string/mod.rs b/crates/napi/src/js_values/string/mod.rs index 6e9c1efb..7dd5c626 100644 --- a/crates/napi/src/js_values/string/mod.rs +++ b/crates/napi/src/js_values/string/mod.rs @@ -109,13 +109,11 @@ impl<'env> JsString<'env> { ) })?; - // respect '\0' with js string, for example: `let hello = [a,'\0',b,'\0',c].join('')` - let mut result = mem::ManuallyDrop::new(result); - let buf_ptr = result.as_mut_ptr(); - let bytes = unsafe { std::slice::from_raw_parts(buf_ptr.cast(), written_char_count) }; + mem::forget(result); + Ok(JsStringUtf8 { inner: self, - buf: bytes, + buf: unsafe { Vec::from_raw_parts(buf_ptr.cast(), written_char_count, written_char_count) }, }) } @@ -161,7 +159,9 @@ impl<'env> JsString<'env> { Ok(JsStringLatin1 { inner: self, buf: unsafe { std::slice::from_raw_parts(buf_ptr.cast(), written_char_count) }, - _inner_buf: vec![], + _inner_buf: unsafe { + Vec::from_raw_parts(buf_ptr.cast(), written_char_count, written_char_count) + }, }) } } diff --git a/crates/napi/src/js_values/string/utf8.rs b/crates/napi/src/js_values/string/utf8.rs index 26a623a9..fbc96011 100644 --- a/crates/napi/src/js_values/string/utf8.rs +++ b/crates/napi/src/js_values/string/utf8.rs @@ -1,20 +1,21 @@ use std::convert::TryFrom; use std::str; -use crate::{bindgen_prelude::ToNapiValue, sys, Error, JsString, Result}; +use crate::{bindgen_prelude::ToNapiValue, sys, Error, JsString, Result, Status}; pub struct JsStringUtf8<'env> { pub(crate) inner: JsString<'env>, - pub(crate) buf: &'env [u8], + pub(crate) buf: Vec, } impl<'env> JsStringUtf8<'env> { pub fn as_str(&self) -> Result<&str> { - Ok(unsafe { str::from_utf8_unchecked(self.buf) }) + str::from_utf8(self.buf.as_slice()) + .map_err(|err| Error::new(Status::InvalidArg, err.to_string())) } pub fn as_slice(&self) -> &[u8] { - self.buf + self.buf.as_slice() } pub fn len(&self) -> usize { diff --git a/examples/napi/__tests__/__snapshots__/values.spec.ts.md b/examples/napi/__tests__/__snapshots__/values.spec.ts.md index 7e64e51d..a4411e14 100644 --- a/examples/napi/__tests__/__snapshots__/values.spec.ts.md +++ b/examples/napi/__tests__/__snapshots__/values.spec.ts.md @@ -832,6 +832,8 @@ Generated by [AVA](https://avajs.dev). ␊ export declare function indexSetToRust(set: Set): void␊ ␊ + export declare function intoUtf8(s: string): string␊ + ␊ export declare function jsErrorCallback(value: unknown): Array␊ ␊ /** default enum values are continuos i32s start from 0 */␊ diff --git a/examples/napi/__tests__/__snapshots__/values.spec.ts.snap b/examples/napi/__tests__/__snapshots__/values.spec.ts.snap index 091348ad7b0cec929b248dacc7baf1a65d4c8bb3..e4f34ab8a470ee4dfc07eba0c219d61aaef85c46 100644 GIT binary patch delta 7238 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 delta 7216 zcmV-09M9vCL5V?sK~_N^Q*L2!b7*gLAa*kf0|4b;y2m7k1?G%=e9Gmgq@q>tcdC9bNY7r^ttx@dNlBY;S2fKzY&oedE&Vgp(ECw%fNS~Z_nf; zh~!`W+Hvg2{^=WUy>a2K3;2H*zkcygegXgf4g7u!zki0`f57kUix)0z!tclM3*q;- z@cS+N{tKGd9I-JB!sPu|_51IA6bTu* z{&>xE2caF#H=JOqYrUy!ee0uWJ`-}o3mjWc^y{zb*YA9E;v$-jK^UCEV(1EQ=?a&0 zg*X}N*Y&$M>=RoTenS_2Z4i$}DWXfd{4E>=th9ddP5t5Z%Wrs8+bRVjKkKYf22$Q z6ie4;UOaYvTAH<4;LS&_=Ou{0n{<&UPM3c#S+`R$Sd&pG?5Rw^b*=B~THl0PPUxP9 z&<)gPIr}r%9xCHNo^jtq$b6jZ;Jb{ImsF^)`J`fMXVCqWo;n6MY zrgda}VWkC^E{U^Q5Ju3Sp=XEKNnb{U{MljuS^uYdcMcx(EIFSJ0y)3H3~xOm`jggT7Dk8p^%pCc|a4wbEFjo z)<9UZc;LCiE}{vdi3m?&(X7ZGTkdoQRej5rmVqAY{qPC0tBz5+`t%agL+R3O`R>&A zXnCN!){k7@v4W9hb1^^}i}nIu_Na=geKc{U1^*8{Gkd{cMnNZq>{`A(6|l^Iz-|5U zY7UWYjcf#%TT>BD0*5il$d25hb?QbFL}6fC?WqAkt+9v*cV|^&M^IguZxw4JMPY3< zBB_fE{Mzx&nS|ANYKAg7bSp1PS1 znxp4&uCK3Wh7CQv8;oh-tLE%~b8DXnSV~+@8BC!g6FY70sW#d5^1o_T=fyR~w)8E?<7h1+S8!gd&PV{{U%n8wm;f2Hh-q z^BCr1JC;!}-8Lu!s^4)#97+H@GjtuX>pSj=>%_LV6^;-5JtBaPAB3=fyhn3AWnEq0 z5k8i_^!1xp8s)1BF2$6B-MK49Hmsh}AKCyWjld(5fgeu?BFxdVS+kp|xVoVEAeob$ zAiU?|6SZq%u7{VhAI&|{p9rAWmx`3b7$g^*RCs*|e?M?#1ei?Lsp0#51O8?y+NvH% zshZ68n7e>y*+V;;U@z2vq-8sBUowK5jA&6KvZ|Gio6dAE!T1Ffd0u&QQnx278bq2Y zTmGu`Rz2AcKn^sROEQ8&G8uoA~W>FtFx=`dT@$a5-dYO}l2Z+_5 z20&k93uO~JHE3{35Wth9inHJG>=$D5&L<#tDLOOxsF-(N2-rV=Tx$T&tGz4;0K_wp zM??pO5_m~+BGftwTqifz3X5v%W)9K9{z1#oxpI8??xs<(0@Jn~4JQYFemghYRz={= zHqiLrU7rPjJlKit#iE`u5ROCQn!COt8lI8`^^uM3sI#(!c#WmrFC2fp0*Wle^)e7m z&3VvUC9sD=0()(Lg@N}@9wdU3v3?#NxFdloSryaR&q@WA_yRu?XUyQHC^hd3;oR<7 zgCOvP?L#T6O6GPgY0#LAyRdQ8?n$SfTgg`Bz10EyIbM*~W`U^5FhE|5M4u|r6q$S9 z7pHVe3u{ta)OU3VP)S z0Kg?}-^?70m3_^ftkp+8owvCm=!3BIEC%LZa?sK=lpVl@kz~&7CWkePTstnPW$x$2 zt#Rr)(M0p6t~C*;f;Zq*gtbptOu8DXayyFUHt5+P;HceA6JbC#X01v{dnCm^tSu_F zDK#sF$=RoW?(U$*WE{l$Ez_!co3KV!z--Tey=?&N*9P$I3aMa0FS?65(OuYw?!qoC zn6F^mPK;pz zHXLyxya1Y8p9Y`1KpX2pINlKc+N1u46Ab0XV=>rBN3d}yfVrafv+=PP3~cWi+bQIR zZu*CM7|(bZ&(s(SEuWsAu9JO^5PP;irlzUU2}}(f6)!eI0mp?DYp}0{+(@gh{l(gi z^+_~;^^)e+xVg2oxe8fs#~ma~qdWbfCKr^)x{7#im7ake1SZ17(NFQ)`RhUO|^}G4%U-G2? z2NZU_NMW)6!VgaU<|GD?t!T`w-Dec>qc&1#XH8LS`KVbswm7GOvx-x$XNoY+^5_G&A<>4-Le zml_gs)lR!fsalGM_V9&07WZY~9}3$kJyqC=i@VPD=arZe@CEQ}sjNiNrw9;bfDb}I zcV}L-^hv5!Qcf)zb9M@cq^R13<>_sxCd#Ht zRVxvlJIC`Cwi4LXuB$7RpfHTT=feGe>ig4e(4Fd~dW=R*nzfAUrKwxS^+B{7*+XG% z5t305nBKTtlcU%lk^_#tdPHsPAn1(TGt>nX2_}xS0ZIZzdu2)? zk@QcGwzZm3c>XX&c*}6ga3_n=KsnS$6J!L^9*G_GqJuShR;MFE5Y6s|VUVtWr5%ow zdA4reLguroPnOmV?SN40C9UOABhKYI${@rdh;utVRWXWpSsr2_PhZI0zkUycBrL3M0B+h z5p6MpqLtEKA|+P0kn+DBU^H4UHP~WfSRG@y4E#el9AMK2@pw|=W7RBw&|r);SRdM< zJ(Vy)p_Vd~DWjTTQv?_u!reLwc*{_ivPVS*YYnnJR7#IdgA7khht&+pLob$BuUzTO z3V^Lq9SSENic->Ui%16EiO_t-N7s8{cuKo{^0W@y5$LJp4)qdb0qtW08C!tr@n}ZC zQ5&7Y$kdt91QnjnJFX{JIx`y`vV~}g`h!_x`V=}}>`-<{DLcDE>}z0$O}G^^@GWN3 z{6K7)|7^hF`91FA-K(4LciKVRxZWJ#V-Y>NaeYgwIEI01bW$3llZ*`~0hp7t4M+md<&*vmO#uXx zOb%r@J`a46O2+s`TQ*xFISTe%&vRvN4r&RFkUa>1I1pl~t|ZW})rWmMa!&-IfgxdR zvUn{FOAX~wlj#me0b`Rf4}~zU^3s$;MJQhilvq3+)=g{k0|P#Br|~~Ks?Ig8qw>@c zvjIc%eGIzPGoJ2e)Y>zX<_|j^mR%)l1V@^6nUdCLVSwwnp;Fs7ILb$EWFanpu#-Lz zBmrKNV-O?)cd3(!5FcQ2JjC4XUN7wx+mU3ihk-07A_Mdc6GLEapSivpxfI189zW$4 zv71Dzywx_?i~o>XHo9!^oke;n@J3KEWFPa^o*B-zjFq&`+zJ#hw4(>GJaD?pqW`@H zupfm>Ks}0+2oWCvRFfzXO#y+Eb`fm>my_fXK?1MQlP3~E8kq{u72`H~Dl)Q6Uvz;n~T%q$kUrGOW0_^n4biT$Y*Jv76 zC>F-XZm+;U>hW`a{Cp*Uw-RFpan`y?VSyE<6ePex?g3tYl#dL5&4380?Pxy>e4)dJ zLuI;wC*fnPGd(PrF^6nF96wlL`^nxX#50$Y13%xrx3l%=!O^qrgZ|M1t5Gop*$5o^ z?+Qg;7W6AjOuzVD)BLJ0MtR49F+=tii^S*Z>O0V zt<3&r6BM^t#Q!7-OXLwfZHRQ|#`S{`7=Xsu*ps5b;XqNDY8t~9G6wi%bws@x=gjvpil%uCc;f$n2mWP|CZ9>JP zU>6oj^s=W}leIz@(4LUe9*b>d4MFyHXC8^pRE`ZXrG{qYR7GfYFwahlgK1!vS|`(g zmKH9+%V~p{56O9meurC%?vuoD8_y z6yIiRgoSZ`j+6qa!vGc0m{$%qHz1AFrGsV2)T%ENi^lEp%E|EauL(1Q;Z}Q zQQMHZ##FEnW*3;@+3S&ri2?;|zHx0yWUtqibL&Om#Gb&A*jxhXLZJDlf-c>oKNeQq z7ob9aqSOvFl8UiUp5p%&1Hv|7fST=~Pt(MN6%3vm!N%F#s>O)%on-aqW4zXoF8t(j zS)%Xe@EA94HCcp$l}zuF+Y78=C6=@1Jj6(2q;;RA&pk88u^BzUd6P<`m1?yK5he0# zr`e8Y+4}?;#}gf>m8J8i%@94()7Ge;k6}N5m0X`z3F4}Ij&p)RdL43ex^T+{mfa=% zU2eI!lDSa11-ADq`t^QWM95C3_6#GZBNaKFWa5?cvL%=twbC{uJOx@VB>cG~F**qo zD_jo1Q$&?+F`IGN{K0w&)t8piR><5Yks>79aX6gd%3{MC-7c-Kn!aO)FC_b}@#->v zmAb{3P%Gr$3PaT&gmp1Cb zhEp2<2^}ztTrmv~l&J{ELS=O#ONg$2_AGi-Jfdqwo7s}p>|@DDlcW$r-YB$U8b_wv zyH3=^OKeU*#rF-f8yJ7(Vcp`aUb5+8;%82ME$ZldbA89{O-}h|VW=v?R>6Q&NA*pL zP7F3>beX+DM|Qsso@ycJ+lm3O9pCkxG- z;A6fd#L+TspW>e$LNh@)MJgCh1e_|wJ6@WZ^B-`I8F%&r>s7Vp&wa(4F;Eb@ukF!s z=2j>}&1{-+zF=aoF+7EhD^rq|9Dy0S!XLUqR^6MCnz1#dRdbNf z3oi$0tXvznj^tW9PyBpQOT}=1N|_F4HncSr z3tuXz3Eh~%0n%1&Nnn=KS`>I{R9e)yv4kQjTe{pAJ=k?~M5#Fm)i*j;v`e(?WXXE~ z$~uy#k3~!B#qz)x6gb^~;~Q=om=$JO-&fY5XGmMc45xaJm%@E$pK=CAMzAo+X}jdZ z21>QWPZWXb^D@~*7;<5agdNe9iZ`t%m(x$pU4Cl4T4do0bqamqAkeFru(Ia#Gv zz-r5Gi=N-w-5#M!36#d5jk_2;!XS(zYKg}E3i=*G$Ao8-c z7SuE1bzL5ErgE}RiX#2uPUIp*SzxFR7hP2vN*!|4xrUM21JZbav%+|4+E*2j)+V(e z)KQXKGEK%@Ca->f`OIIwVRO5AC>{fp9TKZW1+x(r-X-M$BqbzVhZM=RKYdzz-HbW^|7*yGMEN0>ykS778d**!0u?*KSASSE{JEfLHqFS` z4v@jDCO;~p$RhvP|%VJP!=HLR?4=Ph1ufafUSU8J%O2ma~+;0F4V#MBNE-or2Sks)gc zo#>d~;>l`|g=<6WFf+n}^S`0PL{8$!!OJ^1bFiNNC0;wRLsz9I$9XHTbs-WtW@~+#~#VrBp3355eO8tm#!I*!WXBbZtN4nCX=hehSnqsFxf? ztzSl`LFT23t4?0yb0Hj=O}0QM4!MnR(|-XH3%=Wb>{%vC|%Sn{uoe2H20YS z7V3da5ltL>o~zfz3;c{^k}ME82mpc-G>uc5p065U)f5{~Gl4+>As2WS>keK(mkAT3?#41{T|^qE8bJ<^}Y_(cNDS65$HmFvmZA5=+_(3u13S)YA& zdHm;p@(ljrZ$R+ZPC-Oh$prWN2mAQFF-&JyXwiy;fdD=NllKszRb%uC+*m>jE}p$( zai;JBAyNf+;{GW;Ajx~T5NJhi1fH`22z_x1|J@j`@D;>*lsJEC4C`edR!HU+r|2G6 z{4s&<`rB%HvVo@!4gtiK@iZ1Nl=vYRqwAx8-hRg&vl8nKe_-sgS5vm9uZ{L*qj>R_LCeu+K^iNg7ow_Rs;dKTgmo>MO6q}^0eD^Tng+{}F zXtm_qDj0qNZjKtRXh0F+68O_aQMjuFjdL1LH4&V9%fTs`vUqUK&B9SSBh6Y#Mzd`L zKWzxqp97yiGeW`BBYOy|U2}(iO#`6gHB6I5@sefs?q)oL^qNmEw1|!I zgekki0x7p0eFL7vNIXO9{6kT%)F4!U=03SLmw@L@&#Nu2Wh*p{31vYX{UO_@4XLbX zEtHLOY*tf&&fY)|#yNGR0WCfT;VEe?bI3JDawzC4Kz1%vfGmkjxke~%s=^#ebQEq+ zY=0~`jtm8J<%Sf=-pv*tq#xN(@5{6!lI#uTXs9lP$OeaG<@~(DVulZqy7EMS>j{as zHv_Mp(E*J{^98}jad`|UM!L5S;*86KIG4J$B(99&M0EKuPL|gep(_pJ%-llLv}3!z ztANOWnAk&G-Sr(Ol?sX1R7#GErr?E4>k06bCl4kHt# z?Y-(61t;z#=G3MaR43ppJ9XTDR;JhlT3vc>T#wwi-$wq9-bZb5;52uf#uxgTV0;~5 zYfv-_>F#DjW!oT0;uc>c2S+1IB5szrwN>N5P=h^trU$mP6-47BUxeG!!f0c1Qhq?U zg$GE3>SK?`u+Zb(wW!YKZ8L?qM22qMZ7meO-nRrawk14qSx}Qk^9I&`cF2@Hk`Qt% zN!CcYnlEU8m2V`GhD)IFJQss+GiPN}Qc2MiKR(kISF2CiG)9`Z*W6x8m?blno=C+z z`uVy~*^dWYE+4X~uk?;QlIQSy3Tc$Cb(6mjN|K!syj$IUyuWX20IyI^4+9S`D=rIM z>solxCWc;9?LIxU*(un6kjq-B^26+owoYu9x>&DXt9u5UbhS;d&dw$v0b=@Z;XJE2 zj8Q3&Gh9A^-J}ImHB6+N_^Fbb&jpnNUi(RHkBTBnrcc+B{EwgD!;o&xpnyLG#U(${ zHH%+^W9WEB&K-iZ)Kj5Lv}pL=amPZMcl+^OnYu~x(`-H1{dj*p@815AF$LHXbo%P% z`{^{8oi*nMKgv-tC*^bb?8f!#NzA*FXjZn#YnP?J$0 y6D?agCatJa^g@-?#*2SCt7dwQDtAxHKV)n8+$d6^h+#9?%{D diff --git a/examples/napi/__tests__/values.spec.ts b/examples/napi/__tests__/values.spec.ts index 083553d7..0b841cbb 100644 --- a/examples/napi/__tests__/values.spec.ts +++ b/examples/napi/__tests__/values.spec.ts @@ -286,6 +286,7 @@ import { arrayParams, indexSetToRust, indexSetToJs, + intoUtf8, } from '../index.cjs' // import other stuff in `#[napi(module_exports)]` import nativeAddon from '../index.cjs' @@ -337,6 +338,7 @@ test('string', (t) => { t.is(createExternalLatin1String(), 'External Latin1') t.is(createStaticLatin1String(), 'Static Latin1 string') t.is(createStaticUtf16String(), 'Static UTF16') + t.is(intoUtf8('Hello'), 'Hello') }) test('JsStringLatin1::from_external tests', (t) => { diff --git a/examples/napi/example.wasi-browser.js b/examples/napi/example.wasi-browser.js index e41a8511..86c43280 100644 --- a/examples/napi/example.wasi-browser.js +++ b/examples/napi/example.wasi-browser.js @@ -283,6 +283,7 @@ export const i8ArrayToArray = __napiModule.exports.i8ArrayToArray export const indexmapPassthrough = __napiModule.exports.indexmapPassthrough export const indexSetToJs = __napiModule.exports.indexSetToJs export const indexSetToRust = __napiModule.exports.indexSetToRust +export const intoUtf8 = __napiModule.exports.intoUtf8 export const jsErrorCallback = __napiModule.exports.jsErrorCallback export const Kind = __napiModule.exports.Kind export const KindInValidate = __napiModule.exports.KindInValidate diff --git a/examples/napi/example.wasi.cjs b/examples/napi/example.wasi.cjs index f43e40ae..56dfdaf1 100644 --- a/examples/napi/example.wasi.cjs +++ b/examples/napi/example.wasi.cjs @@ -328,6 +328,7 @@ module.exports.i8ArrayToArray = __napiModule.exports.i8ArrayToArray module.exports.indexmapPassthrough = __napiModule.exports.indexmapPassthrough module.exports.indexSetToJs = __napiModule.exports.indexSetToJs module.exports.indexSetToRust = __napiModule.exports.indexSetToRust +module.exports.intoUtf8 = __napiModule.exports.intoUtf8 module.exports.jsErrorCallback = __napiModule.exports.jsErrorCallback module.exports.Kind = __napiModule.exports.Kind module.exports.KindInValidate = __napiModule.exports.KindInValidate diff --git a/examples/napi/index.cjs b/examples/napi/index.cjs index e8835b3f..c01836b5 100644 --- a/examples/napi/index.cjs +++ b/examples/napi/index.cjs @@ -728,6 +728,7 @@ module.exports.i8ArrayToArray = nativeBinding.i8ArrayToArray module.exports.indexmapPassthrough = nativeBinding.indexmapPassthrough module.exports.indexSetToJs = nativeBinding.indexSetToJs module.exports.indexSetToRust = nativeBinding.indexSetToRust +module.exports.intoUtf8 = nativeBinding.intoUtf8 module.exports.jsErrorCallback = nativeBinding.jsErrorCallback module.exports.Kind = nativeBinding.Kind module.exports.KindInValidate = nativeBinding.KindInValidate diff --git a/examples/napi/index.d.cts b/examples/napi/index.d.cts index 62cb28f1..8b377030 100644 --- a/examples/napi/index.d.cts +++ b/examples/napi/index.d.cts @@ -793,6 +793,8 @@ export declare function indexSetToJs(): Set export declare function indexSetToRust(set: Set): void +export declare function intoUtf8(s: string): string + export declare function jsErrorCallback(value: unknown): Array /** default enum values are continuos i32s start from 0 */ diff --git a/examples/napi/src/string.rs b/examples/napi/src/string.rs index e24e4c66..c7daf5b9 100644 --- a/examples/napi/src/string.rs +++ b/examples/napi/src/string.rs @@ -1,4 +1,4 @@ -use napi::{bindgen_prelude::*, JsString, JsStringLatin1, JsStringUtf16}; +use napi::{bindgen_prelude::*, JsString, JsStringLatin1, JsStringUtf16, JsStringUtf8}; #[napi(object)] pub struct Latin1MethodsResult { @@ -40,6 +40,11 @@ pub fn return_c_string() -> RawCString { RawCString::new(mock_c_string_ptr, NAPI_AUTO_LENGTH) } +#[napi] +pub fn into_utf8(s: JsString) -> Result { + s.into_utf8() +} + #[napi] /// Function to test escaped quotes in comments. /// This comment contains escaped quotes: \\"g+sx\\" and should not break JSON parsing.