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.8k
Other Decks in Programming
See All in Programming
Kotlinの15年とServer-Side Kotlin
n_takehata
1
150
Compiling a real-world CLI tool to native with Static Hermes
tmikov2023
0
120
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
2
630
コードで差別化できない時代の ソフトウェアエンジニアリング / Software Engineering in an Era Where Code Doesn’t Differentiate
kishida
2
180
SREの越境 / SRE Collaboration
y0hgi
2
310
phperだってパンチカードでコーディングしたい
o0h
PRO
0
330
コーディング自動化の次へ。人の介入をゼロにするファクトリーとサポートAIによる実践
timakin
4
3.5k
ソニーのクラウド共通基盤の変遷とAI時代の開発スタイルに合わせた進化 / The Journey of Sony’s Common Cloud Platform and Its Evolution for AI-Native Development
kenjiyoneyama
0
270
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
300
AI時代のコードレビューは人に向けるな、仕組みに向けろ
texmeijin
5
3.7k
dotNET_vulnclicker_intro.pdf
deka_morita
0
140
當我們開始不讀 Code - AI Agent 時代,Code Review 與 Clean Code 還剩下什麼?
jame2408
1
190
Featured
See All Featured
New Earth Scene 8
popppiees
4
2.7k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Code Reviewing Like a Champion
maltzj
529
40k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
203
77k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
2
6.3k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
480
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
18k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
410
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
330
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
1
280
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