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
ゆい
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.9k
Other Decks in Programming
See All in Programming
Rails初心者がパスキーを実装してみて大変だったこと
ktombow
0
160
protojson における文字化けの扱い
kazuki1023
0
220
Kotlinize Is Not Just Converting to Kotlin
chigichan24
1
220
地方こそサーバーレス — 10年続けた、顔が見えるチームで確かな基盤を / Serverless Matters Most in Regional Areas — 10 Years of Building Reliable Foundations with Close-Knit Teams
seike460
PRO
1
330
當我們開始不讀 Code - AI Agent 時代,Code Review 與 Clean Code 還剩下什麼?
jame2408
1
370
複数ドメインを一つのアプリに統合するFlutterの設計と運用_FlutterKaigi2026登壇資料(須永高弘)
takahirosunaga
0
160
PyConTW 2026 - AI Coding 不只是工具升級, 區域醫院醫療資訊系統協作開發與資訊團隊轉型實踐
cclai999
0
240
AIが実装を担う時代の「技術設計」と「チームマネジメント」
kamina_zzz
2
240
SODA - FACT BOOK(JP)
sodainc
1
40k
AI時代のFlutter品質設計 — アプリ品質を守るQuality Layers
omatty198
0
360
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
3
1.5k
Getting Started with Vibe Coding
miccheng
0
190
Featured
See All Featured
What the history of the web can teach us about the future of AI
inesmontani
PRO
3
800
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
370
How to build a perfect <img>
jonoalderson
1
6.2k
Rails Girls Zürich Keynote
gr2m
96
14k
Accessibility Awareness
sabderemane
1
290
Agile that works and the tools we love
rasmusluckow
331
22k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
[SF Ruby Conf 2025] Rails X
palkan
3
1.5k
The Curious Case for Waylosing
cassininazir
1
610
Amusing Abliteration
ianozsvald
1
380
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
400
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.9k
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