Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
PHPの緩やかな比較の実態
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
ゆい
April 11, 2022
Programming
1.7k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
PHPの緩やかな比較の実態
ゆい
April 11, 2022
More Decks by ゆい
See All by ゆい
LaravelでLIKE句のSQLインジェクション対策をする
fyui001
0
3.8k
Other Decks in Programming
See All in Programming
[ハンズオン]AIへの指示だけで「五目並べ」を作ってみよう
satoshi256kbyte
0
120
Jetpack Compose メカニズム
skydoves
0
470
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
160
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
210
AGENTS.md Is Not Enough:Build Skills, Don't Download Them
lx_t
0
130
iOSDC2026登壇資料.pdf
riofujimon
0
180
フロントエンドUIフレームワークのこれまでとこれから
ssssota
5
2.9k
アクセシビリティから考える情報設計
high_g_engineer
0
400
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
440
パズルゲームの作り方 / how to make puzzle games
kaityo256
PRO
2
210
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
160
thread_parallel_with_free-threaded_Python_and_NumPy.pdf
riku_sakamoto
0
360
Featured
See All Featured
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
340
Leo the Paperboy
mayatellez
10
2.3k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
300
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.7k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
340
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
200
Designing Experiences People Love
moore
143
24k
Thoughts on Productivity
jonyablonski
76
5.4k
The Invisible Side of Design
smashingmag
301
52k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
830
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
250
Transcript
Copyright© M&AΫϥυ PHPͷ؇͔ͳൺֱͷ࣮ଶ PHPerKaigi 2022
Copyright© M&AΫϥυ 2 Profile גࣜձࣾM&AΫϥυ ᅳଜʢΏ͍ʣ fyui001 @fyui_001
Copyright© M&AΫϥυ 3 ֓ཁ PHPʹՁԋࢉࢠ͕2ͭ͋Γ·͢ɻʮ==ʯͱʮ===ʯͰ͢ɻ લऀ؇͔ͳൺֱɺޙऀݫີͳൺֱ͕ߦΘΕ·͢ɻ PHPerͷํͳΒΑ͘͝ଘͩͱࢥ͍·͢ɻ ࠓճલऀͷ؇͔ͳൺֱΛ࣮ଶ͕Ͳ͏ͳ͍ͬͯΔͷ͔Λͬͯݟ͍ͨͱࢥ͍·͢ɻ
Copyright© M&AΫϥυ 4 ؇͔ͳൺֱͷΧΦε͞ ྫ: <?php var_dump(0 == '00'); var_dump('00'
== '0000'); var_dump('01' == '001'); ग़ྗ: bool(true) bool(true) bool(true)
Copyright© M&AΫϥυ 5 ؇͔ͳൺֱͷΧΦε͞ ͍ɺҙຯΘ͔Γ·ͤΜɻ 1, 2ߦཧղͰ͖ͳ͍͜ͱ͋Γ·ͤΜ͕ 3ߦ͕ԿނtrueʹͳΔͷ͔ɺݫີʹઆ໌͢ΔʹͲ͏ͨ͠Β͍͍Ͱ͠ΐ ͏͔ɻ ͜ͷൃදΛฉ͍ͯཧղ͠આ໌Ͱ͖ΔΑ͏ʹͳͬͯ͑Εخ͍͠Ͱ͢ɻ
Copyright© M&AΫϥυ 6 ؇͔ͳൺֱͷ࣮ମͲ͜ʹ͋Δͷ͔ ݴޠ༷ʹؔ͢Δઆ໌υΩϡϝϯτΛಡΊྑ͍ͷͰ͕͢ɺ ࠷ਖ਼֬ͳυΩϡϝϯτԿͰ͠ΐ͏ɻ ͦΕιʔείʔυͰ͢ɻ ιʔείʔυͱͦΕΛઆ໌͍ͯ͠ΔυΩϡϝϯτʹࠩҟ͕͋ͬͯɺͦ ͷιʔείʔυͰಈ͍͍ͯΔҎ্ιʔείʔυ͕ਖ਼֬ͳυΩϡϝϯτ ʹͳΓ·͢ɻ
PHPͷ؇͔ͳൺֱΛߦ͍ͬͯΔιʔείʔυຊମΛݟͯΈ·͠ΐ͏ɻ
Copyright© M&AΫϥυ 7 ؇͔ͳൺֱͷ࣮ମͲ͜ʹ͋Δͷ͔ ࠓճPHP8.0.9ͷιʔείʔυΛಡΜͰ͍͜͏ͱࢥ͍·͢ɻ
Copyright© M&AΫϥυ 8 ιʔείʔυͷམͱ͠ํ ·ͣී௨ʹgit clone͠·͢ git clone https://github.com/php/php-src
Copyright© M&AΫϥυ 9 ιʔείʔυͷམͱ͠ํ ࠓͷphp-srcͷ࠷৽PHP8.1.4ͷRCʹͳ͍ͬͯΔͷͰɺ8.0.9ʹΞοϓ σʔτ͞ΕͨίϛοτΛಛఆͯ͠νΣοΫΞτͯ͋͛͠·͢ɻ git checkout a5368c55be0a42af9fdc2c76fb0c2a06a42ddf36
Copyright© M&AΫϥυ 10 PHPͷ؇͔ͳൺֱͷ࣮ଶ ʊਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓʊ ʼɹPHPͷ؇͔ͳൺֱಈ࡞Λݫີʹઆ໌Ͱ͖Δਓ͔͍͚ͬͯ͠·ͤΜɻɹʻ ʉY^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ʉ
Copyright© M&AΫϥυ 11 ֘ιʔεʹḷΓண͘ํ๏ ϊʔώϯτͰPHPͷιʔείʔυΛಡΜͰɺతͷॴʹͨͲΓண ͚ͳ͚Εҙຯ͕͋Γ·ͤΜɻ ݴޠಛ༗ͷԋࢉࢠΛจࣈྻͰgrepIDEͷϑΝΠϧݕࡧΛͯ͠Έ·͢ɻ ࠓճӉધԋࢉࢠ(<=>)Ͱݕࡧͯ͠Έ·͢ɻ
Copyright© M&AΫϥυ 12 ֘ιʔεʹḷΓண͘ํ๏ ͳΜ͔ͦΕͬΆ͍ϑΝΠϧ͕ݟ͔ͭΓ·ͨ͠ɻ PHPͷԋࢉࢠΛจࣈྻͱͯ͠ఆ͍ٛͯ͠ΔࠜຊZend/ zend_language_parser.yʹ͋Γͦ͏Ͱ͢ɻ ※.yͷ֦ுࢠͷϑΝΠϧߏจղੳػΛੜ͢ΔͨΊʹɺYaccͱݴ͏πʔ ϧͷϑΝΠϧͷԋࢉࢠͰ͢ɻ Zend/zend_language_parser.yΛ։͍ͯΈ·͢ɻ
Copyright© M&AΫϥυ 13 ֘ιʔεʹḷΓண͘ํ๏ Ӊધԋࢉࢠͷ্͙͢ʹո͍͠ߦ͕͋Γ·ͨ͠ɻ తͷʮ==ʯT_IS_EQUALͱ͍͏໊લ͕͍͍ͯΔΈ͍ͨͰ͢ɻ Zend/zend_language_parser.yͰT_IS_EQUALΛݕࡧ͢Δͱ
Copyright© M&AΫϥυ 14 ֘ιʔεʹḷΓண͘ํ๏ ͜Μͳιʔε͕ݟ͔ͭΓ·͢ɻ Ͳ͏ΒZEND_IS_EQUALͱ͍͏໊લͰதؒίʔυʹม͞ΕΔΈͨ ͍Ͱ͢ɻ
Copyright© M&AΫϥυ 15 ZEND_IS_EQUALͱݴ͏ϫʔυΛෳϑΝΠϧݕࡧ͢Δͱɺ Zend/zend_opcode.cʹ͜Μͳߦ͕͋Γ·ͨ͠ case ZEND_IS_EQUAL:
Copyright© M&AΫϥυ 16 Zend/zend_opcode.cͷத END_API binary_op_type get_binary_op(int opcode) { switch
(opcode) { /* ~~~~~~~~~~ */ case ZEND_IS_EQUAL: case ZEND_CASE: return (binary_op_type) is_equal_function; case ZEND_IS_NOT_EQUAL: return (binary_op_type) is_not_equal_function; /* ~~~~~~~~~~ */ default: ZEND_UNREACHABLE(); return (binary_op_type) NULL; } } ͜Μͳͷ͕͍·ͨ͠ɻ ZEND_IS_EQUALis_equal_functionͱ͍͏ؔʹରԠ͍ͯ͠ΔΑ͏Ͱ͢Ͷɻ is_equal_functionͰݕࡧΛ͔͚ͯΈ·͢ɻ
Copyright© M&AΫϥυ 17 is_equal_functionͰݕࡧΛ͔͚ͯΈΔ ZEND_API int ZEND_FASTCALL is_equal_function(zval *result, zval
*op1, zval *op2) Zend/zend_operators.cʹḷΓண͖·ͨ͠ɻ ϊʔώϯτͰɺIDEͷϑΝΠϧݕࡧͰେͨ࣌ؒ͠Λ͔͚ͣʹ΄͍͠ ใ·ͰḷΓண͚·͢ɻ ϥΠϒϥϦͷதΛௐ͍ͨͱ͖ʹ͑ΔͷͰࢀߟʹͯ͠Έͯ͘ ͍ͩ͞ɻ
Copyright© M&AΫϥυ 18 ؇͔ͳൺֱͷਖ਼ମݟͨΓʂ is_equal_functionzend_compareͱݴ͏ؔʹରԠ͍ͯ͠ΔΑ͏Ͱ͢ɻ /* == ͷॲཧ */ ZEND_API
zend_result ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */ { ZVAL_BOOL(result, zend_compare(op1, op2) == 0); return SUCCESS; } /* }}} */
Copyright© M&AΫϥυ 19 ؇͔ͳൺֱͷਖ਼ମݟͨΓʂ ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval
*op2) /* {{{ */ { int converted = 0; zval op1_copy, op2_copy; while (1) { switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { case TYPE_PAIR(IS_LONG, IS_LONG): return Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ case TYPE_PAIR(IS_LONG, IS_DOUBLE): return ZEND_NORMALIZE_BOOL((double)Z_LVAL_P(op1) - Z_DVAL_P(op2)); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ case TYPE_PAIR(IS_ARRAY, IS_ARRAY): return zend_compare_arrays(op1, op2); case TYPE_PAIR(IS_NULL, IS_NULL): /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ case TYPE_PAIR(IS_STRING, IS_STRING): if (Z_STR_P(op1) == Z_STR_P(op2)) { return 0; } return zendi_smart_strcmp(Z_STR_P(op1), Z_STR_P(op2)); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ default: if (Z_ISREF_P(op1)) { op1 = Z_REFVAL_P(op1); continue; } else if (Z_ISREF_P(op2)) { op2 = Z_REFVAL_P(op2); continue; } if (Z_TYPE_P(op1) == IS_OBJECT && Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_P(op1) == Z_OBJ_P(op2)) { return 0; } else if (Z_TYPE_P(op1) == IS_OBJECT) { return Z_OBJ_HANDLER_P(op1, compare)(op1, op2); } else if (Z_TYPE_P(op2) == IS_OBJECT) { return Z_OBJ_HANDLER_P(op2, compare)(op1, op2); } if (!converted) { if (Z_TYPE_P(op1) < IS_TRUE) { return zval_is_true(op2) ? -1 : 0; } else if (Z_TYPE_P(op1) == IS_TRUE) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ } else { op1 = _zendi_convert_scalar_to_number_silent(op1, &op1_copy); op2 = _zendi_convert_scalar_to_number_silent(op2, &op2_copy); if (EG(exception)) { return 1; /* to stop comparison of arrays */ } converted = 1; } } else if (Z_TYPE_P(op1)==IS_ARRAY) { return 1; } else if (Z_TYPE_P(op2)==IS_ARRAY) { return -1; } else { ZEND_UNREACHABLE(); zend_throw_error(NULL, "Unsupported operand types"); return 1; } } } } /* }}} */ php-src/Zend/zend_operators.c
Copyright© M&AΫϥυ 20 ؇͔ͳൺֱͷਖ਼ମݟͨΓʂ ͍... ͏ͳΜ͔ΠϠͳ༧ײ͕͠·͢Ͷɻ தΛཁ͍ͯ͘͠ͱɺԋࢉࢠͷࠨӈͷΦϖϥϯυͷܕͷΈ߹ΘͤʹԠͯ͡ɺ ྑ͍ײ͡ʹॲཧΛذͯ͠ฦ͍ͯ͠ΔΈ͍ͨͰ͢ɻ ಉ࢜ͷൺֱී௨ʹߦΘΕ͍ͯ·͕͢ɺจࣈྻͷൺֱͳΜ͔͕ؔݺΕͯ·͢ɻ case
TYPE_PAIR(IS_STRING, IS_STRING): if (Z_STR_P(op1) == Z_STR_P(op2)) { return 0; } return zendi_smart_strcmp(Z_STR_P(op1), Z_STR_P(op2)); zendi_smart_strcmpͱݴ͏ո͍͕ؔ͠ݺΕ͍ͯ·͢ɻ ͲΜͳౕ͔ݟͯΈ·͠ΐ͏ɻ
Copyright© M&AΫϥυ 21 zendi_smart_strcmpͱݴ͏ո͍ؔ͠ ZEND_API int ZEND_FASTCALL zendi_smart_strcmp(zend_string *s1, zend_string
*s2) /* {{{ */ { zend_uchar ret1, ret2; int oflow1, oflow2; zend_long lval1 = 0, lval2 = 0; double dval1 = 0.0, dval2 = 0.0; if ((ret1 = is_numeric_string_ex(s1->val, s1->len, &lval1, &dval1, false, &oflow1, NULL)) && (ret2 = is_numeric_string_ex(s2->val, s2->len, &lval2, &dval2, false, &oflow2, NULL))) { #if ZEND_ULONG_MAX == 0xFFFFFFFF if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. && ((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/) || (oflow1 == -1 && dval1 < -9007199254740991.))) { #else if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) { #endif /* both values are integers overflown to the same side, and the * double comparison may have resulted in crucial accuracy lost */ goto string_cmp; } if ((ret1 == IS_DOUBLE) || (ret2 == IS_DOUBLE)) { if (ret1 != IS_DOUBLE) { if (oflow2) { /* 2nd operand is integer > LONG_MAX (oflow2==1) or < LONG_MIN (-1) */ return -1 * oflow2; } dval1 = (double) lval1; } else if (ret2 != IS_DOUBLE) { if (oflow1) { return oflow1; } dval2 = (double) lval2; } else if (dval1 == dval2 && !zend_finite(dval1)) { /* Both values overflowed and have the same sign, * so a numeric comparison would be inaccurate */ goto string_cmp; } dval1 = dval1 - dval2; return ZEND_NORMALIZE_BOOL(dval1); } else { /* they both have to be long's */ return lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0); } } else { int strcmp_ret; string_cmp: strcmp_ret = zend_binary_strcmp(s1->val, s1->len, s2->val, s2->len); return ZEND_NORMALIZE_BOOL(strcmp_ret); } } /* }}} */
Copyright© M&AΫϥυ 22 zendi_smart_strcmpͱݴ͏ո͍ؔ͠ ͏͑ʙ ॲཧͷ༰ɺ • ೖྗ͞Εͨจࣈྻ͕ʮͱͯ͠ධՁͰ͖Δ߹ͱͯ͠ѻ͍ൺֱ͢Δʯ • ͱͯ͠ධՁग़དྷͳ͍߹จࣈྻಉ࢜ͷൺֱΛߦ͏
strcmp໋໊ͬͯͳΜͳΜͩ... ͭ·Γstrcmpͱ໊͔ΓͰɺจࣈྻͱͯ͠ҟͳ͍ͬͯͯͱͯ͠߹͍ͬͯΕ true Ͱ͢ɻ ୭ͩ͜ΜͳΫιΈ͍ͨͳ༷ࢥ͍͍ͭͨͭʙ
Copyright© M&AΫϥυ 23 PHPͷ؇͔ͳൺֱͷ࣮ଶ ͜ΕΛ౿·͑ͯ͏ҰίʔυΛݟͯΈ·͠ΐ͏ ιʔείʔυɿ <?php var_dump(0 == '00');
var_dump('00' == '0000'); var_dump('01' == '001'); ग़ྗɿ bool(true) bool(true) bool(true) ͜ΕͰ಄ͷίʔυͷ࣮ߦ݁ՌͷṖ༹͕͚ͨͱࢥ͍·͢ɻ
Copyright© M&AΫϥυ 24 ݫີͳൺֱͷιʔεͲ͜ʁ Zend/zend_operators.cʹ͍·͢ɻ ZEND_API zend_bool ZEND_FASTCALL zend_is_identical(zval *op1,
zval *op2) /* {{{ */ { if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { return 0; } switch (Z_TYPE_P(op1)) { case IS_NULL: case IS_FALSE: case IS_TRUE: return 1; case IS_LONG: return (Z_LVAL_P(op1) == Z_LVAL_P(op2)); case IS_RESOURCE: return (Z_RES_P(op1) == Z_RES_P(op2)); case IS_DOUBLE: return (Z_DVAL_P(op1) == Z_DVAL_P(op2)); case IS_STRING: return zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); case IS_ARRAY: return (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2) || zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1) == 0); case IS_OBJECT: return (Z_OBJ_P(op1) == Z_OBJ_P(op2)); default: return 0; } } /* }}} */
Copyright© M&AΫϥυ 25 ݫີͳൺֱͷιʔεͲ͜ʁ ·ͣ࠷ॳʹܕҧ͍ͰfalseʹͳΓ·͢ɻ ܕ͕Ұக্ͨ͠ͰɺͦΕͧΕͷܕͰγϯϓϧͳൺֱΛ͍ͯ͠·͢ɻ ʮ==ʯͷιʔείʔυΑΓང͔ʹγϯϓϧͰ͢ɻ
Copyright© M&AΫϥυ 26 ͍͞͝ʹ ࣗࠓ·ͰͳΜͱͳ͘Ͱ͔͠ɺཧղͯ͠ͳ͔ͬͨͰ͕͢ɺࠓճͷௐ ࠪͰͲΕ͚ͩةݥͳ͔Α͘ཧղͰ͖·ͨ͠ɻ օ͞ΜPHPͷൺֱԋࢉࢠͬͯݫ֨ͳൺֱΛ͍·͠ΐ͏ɻ
Copyright© M&AΫϥυ ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ 27