JavaScript 的動態執行可能比你想像中還要無孔不入

realdennis
3 min readOct 4, 2018

--

許多方式都會觸發動態執行,這些動態執行一來是非常地難去做測試,二來是捉摸不定,但除了常見的 eval function 、 script tag 以外,還有其他意想不到的方式會變成動態執行…

“chimpanzee holding mirror” by Andre Mouton on Unsplash

JS仔都知道JavaScript 本身有許多的動態執行的坑,一般人不太會喜歡這種特性,甚至在某些書中直接嚴重警告不該使用這些 function

除非在某些你想繞過根本問題 (root cause) ,快速解決當下問題的狀況,不過通常看起來會很 hard code 。

比如眾所皆知的 eval function ,甚至有 don’t be eval (evil) 的俗諺,可以參考 Stack Overflow 的這篇文章 Why is using the JavaScript eval function a bad idea?

  • 誤用 eval 可能會被 code injection
  • 難以抓蟲 (error 在字串的哪?)
  • 效能較差

eval 可以被傳入某字串或字串參數,

以上狀況就如同 innerHtml 被惡意插入其他tag一樣

這裡稍微提一下,雖然 JavaScript 多數時候是 client side program ,但是並不代表這 code injection 不重要,這類的 injection 輕則導致程式 crash,重則成為 XSS

竟然身為一個 programmer 就不要 coding 時還抱著使用者出問題只要 refresh 就好了的心態…

除了最顯為人知的 eval 以外, innerHtml 主動加入 script 標籤,以及使用document.createElement('script') 並把 src 指向欲動態執行的位置(例如:常見的 JSONP ),也是常見的動態執行方法,好處是程式體積小,依靠網路或 I/O 動態加載。

最為致命的是,你根本不知道你的 code 竟然做了動態加載。

少見的動態加載如同 setTimeout 系列,這個挺冷門的。

setTimeout(“console.log(‘hello’)”,1000); // 一秒後會印出hello字串

咦? setTimeout 不是傳入 function callback 嗎?

不對欸,不對,你這樣一傳還真的會印出來。

(function(){
setTimeout(‘var gl=20’,1000)
})()

而且你猜這個 function 會發生什麼鳥事

因為 setTimeout 本身帶的是 callback function ,而你直接宣告 var gl=20 ,對於這個 callback 來說是裸露在外頭的,不信你過 1 秒後看看 window.gl 是不是 20 ?

在瀏覽器的console試試看吧!

其實,只是想打一篇廢文來分享 setTimeout 這個坑,原本是在 paper 看到時還難以置信(畢竟才疏學淺),其他 setXxxxx 系列的 timer 也會有這問題,可以自行替換成 setInterval 試試看。

--

--

No responses yet