Siorki / RegPack

Self-contained packer for size-constrained JS code
Other
298 stars 14 forks source link

RegPacked code contains invalid escape sequences #65

Closed xem closed 7 years ago

xem commented 7 years ago

Hello,

I'm trying to pack the following code:

b.innerHTML=`<div style=width:95vw;height:95vh;perspective:500px;overflow:hidden;background:#7e2><div style=transform-style:preserve-3d;margin:50vh+50vw;transform-origin:0+0 id=s><div style=width:55px;font:40px'' id=h>🐰<div style=transform:rotate(180deg)translateY(9px);font:50px''>🎩`;k=[];onkeydown=e=>k[e.which-37]=1;onkeyup=e=>k[e.which-37]=0;x=-400;y=-630;a=1.35;m=[0,10240,45022,59464,27080,59658,114174,0];z=1;for(i in m){for(H=17;H--;){if(m[i]>>H&1){s.innerHTML+=`<div style=width:255px;height:255px;background:#b31;position:fixed;top:${250*i}px;left:${250*H}px>`;}else s.innerHTML+=`<div id=t${i+H} style=font-size:120px;position:fixed>${[...'🌳🌲🌡'][(i*H+z++)%3]}`;}}s.innerHTML+=`<div id=t${616} style=font-size:30px>πŸ₯•`;t=0;c=0;setInterval(e=>{t+=.3;v=x;w=y;if(k[2])a-=.05;else if(k[0])a+=.05;else if(k[1]){y+=20*Math.cos(a);x+=20*Math.sin(a)}else if(k[3]){y-=20*Math.cos(a);x-=20*Math.sin(a)}if(!(m[~~(-y/250)]>>(~~(-x/250))&1)){x=v;y=w}h.style.transform=`translateX(${-x-20}px)translateY(${-y-20}px)translateZ(${60-14*Math.sin(t)}px)rotateZ(${-a}rad)rotateX(-90deg)`;if(!c)s.style.transform=`rotateX(55deg)rotateZ(${a}rad)translateX(${x}px)translateY(${y}px)`;else{s.style.transition=`5s`;s.style.transform=`rotateX(30deg)translateX(-2200px)translateY(-2000px)translateZ(-2000px)`;a=0;}for(i in m){for(H=17;H--;){if(self[`t${i+H}`]){if(c)self[`t${i+H}`].style.transition=`5s`;self[`t${i+H}`].style.transform=`translateX(${H*250+99}px)translateY(${i*250-99}px)translateZ(160px)rotateZ(${-a}rad)rotateX(-90deg)scale(2.5)`;}}}if(x<-4100)c=1},33)

Regpack 5.0.0 produced the following output (with the tie 2/1/0)

for(_="(-\${jerqpx|transK|)JKlate_}J_^(jW_XWV55|UforS0;RinQ50P20OstyleNKSmG.N.G=`FrotateEsFEX(D.QnqHTMLCsC+=`B2PA:jA*@ition?){elseif( k[=.05;a}rad)*Math.;onkeyfont id=`;\O00J^YW=OsQ(a)};height:deg)cos(a);x<div N=width:.N.K?=`5s ;background:#;pos?:fixed} N=-size:=e=>k[e.which-37]=self[`tji+H}`]B<divtjS(i Q mS(H=17;H--;JEZW-EX\90bC=`95vw95vh;pqspective:P0|;ovqflow:hidden7e2>G-N:presqve-3d;margQ:Pvh+Pvw;G-origQ:0+0s>U;:40|''h>🐰G:E(180_Y(9J;:P|''>🎩k=[]down1upRx=-40Ry=-63Ra=1.35;m=[0,10240,4P22,59464,27080,59658,114174,0];z=1;m[i]>>H&1B2U2Ub31;top@i}|;left@H}|>} i+H1O|>j[...'🌳🌲🌡'][(i*H+z++)%3]}}}61630|>πŸ₯•t=Rc=RsetIntqval(e=>{t+=.3;v=x;w=y;k[2])a-0])a+1]y++3]y--!(m[~~\y/A)]>>(~~\x/A))&1)x=v;y=w}hFV-x-O-y-O^ZW60-14sQ(t)}!c)D55EZWVxy}J{s  D30_X\2O0J_Y_Za=R}c)   FVH*A+99i*A-99^Z(160scale(2.5)}}}x<-4100)c=1},33)";G=/[-?-GN-SU-W^_JK|qj\\]/.exec(_);)with(_.split(G))_=join(shift());eval(_)

When I try to execute that, my browser tells me:

Uncaught SyntaxError: Invalid hexadecimal escape sequence

more precisely, RegPack uses the token "\" for compression, but when \ is placed before a "x", it breaks the string:

(~~\x/A))

I tried to exclude "\" from the "reassign variables except..." field but it didn't work. The quick fix will probably be to rename my var x into something else, but I thought you'd like to know this issue :)

Thanks!

Siorki commented 7 years ago

The reason behind this issue is that \ as a token is not correctly escaped. So it is treated as an escaping sequence - \x with your code - instead of being decoded as a single \. Even worse, the safeguard (automatic unpacking at the end of the routine) and linked unit tests failed to catch that.

This may prove be quite tricky to fix entirely. I got a quickfix to solve your case, but it would invalidate the replacement in regPack.js:515-557. Performing the escaping at the end of the routine, instead of the beginning, could do the trick, however it also needs to figure out when not to use \ as a token as it basically costs double compared to other characters.

As a workaround, you could revert to v4.0.1, it does not suffer from the issue and compresses the sample code to 1017b.

xem commented 7 years ago

thanks for the analysis. Don't worry for my case, my code has changed since this bug and doesn't enable the '\' token anymore when I pack it. Cheers and good luck!

Siorki commented 7 years ago

Moved the escaping after tokens are assigned. This does the trick.