3
1

More than 1 year has passed since last update.

filter_varの検証フィルタ「FILTER_VALIDATE_DOMAIN」の動作を確認するためにphptファイルにテストパターンを追加して実行してみた

Last updated at Posted at 2022-09-06

この記事を書くきっかけ

2022年9月24日、25日に開催される「PHP Conference Japan 2022」で「FQDN(ドメイン名)のバリデーションが意外と面倒だった」というタイトルで登壇予定なんですが、登壇スライドを作成している途中に調査したphptについてはLT(4分)の枠内に収められそうにないので、こちらでまとめておこうと思った次第です。

動作確認環境

  • PC: MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)
  • OS: macOS Monterey 12.0.1
  • CPU: 2.3 GHz クアッドコア Intel Core i7
  • Memory: 32 GB

事前準備

任意のディレクトリにPHP 8.1.10(2022年9月8日時点の最新版)のソースをダウンロード。

% curl -LO https://www.php.net/distributions/php-8.1.10.tar.gz

展開したディレクトリへ移動。

% tar zxf php-8.1.10.tar.gz
% cd php-8.1.10

libiconv を未インストールの状態で ./configure を実行すると以下のようなエラーが発生する。

% ./configure 
・
・
configure: error: Please specify the install prefix of iconv with --with-iconv=<DIR>

libiconv をインストールする場合は以下のように実行する。

% brew install libiconv
% ./configure --with-iconv=/usr/local/opt/libiconv

libiconv をインストールしない場合は以下のように実行する。

% ./configure --without-iconv

filter_varの「FILTER_VALIDATE_DOMAIN」に対応するphptファイルを探す

grep してみると、どうやら ext/filter/tests/056.phpt が目的のファイルと思われる。

% grep 'FILTER_VALIDATE_DOMAIN' * -r |grep phpt
ext/filter/tests/056.phpt:filter_var() and FILTER_VALIDATE_DOMAIN
ext/filter/tests/056.phpt:    var_dump(filter_var($value, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME));
ext/filter/tests/056.phpt:var_dump(filter_var('_example.com', FILTER_VALIDATE_DOMAIN));
ext/filter/tests/056.phpt:var_dump(filter_var('_example.com', FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME));
ext/filter/tests/056.phpt:var_dump(filter_var('test_.example.com', FILTER_VALIDATE_DOMAIN));
ext/filter/tests/056.phpt:var_dump(filter_var('test_.example.com', FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME));
ext/filter/tests/056.phpt:var_dump(filter_var('te_st.example.com', FILTER_VALIDATE_DOMAIN));
ext/filter/tests/056.phpt:var_dump(filter_var('te_st.example.com', FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME));
ext/filter/tests/056.phpt:var_dump(filter_var('test._example.com', FILTER_VALIDATE_DOMAIN));
ext/filter/tests/056.phpt:var_dump(filter_var('test._example.com', FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME));
ext/filter/tests/filter_null_on_failure.phpt:var_dump(filter_var(".invalid", FILTER_VALIDATE_DOMAIN, FILTER_NULL_ON_FAILURE));

ファイルの中身を確認すると、それっぽい内容が書かれている。

ext/filter/tests/056.phpt
% cat ext/filter/tests/056.phpt
--TEST--
filter_var() and FILTER_VALIDATE_DOMAIN
--EXTENSIONS--
filter
--FILE--
<?php

$values = Array(
'example.com',
'www.thelongestdomainnameintheworldandthensomeandthensomemoreandmore.com',
'toolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolong.com',
'eauBcFReEmjLcoZwI0RuONNnwU4H9r151juCaqTI5VeIP5jcYIqhx1lh5vV00l2rTs6y7hOp7rYw42QZiq6VIzjcYrRm8gFRMk9U9Wi1grL8Mr5kLVloYLthHgyA94QK3SaXCATklxgo6XvcbXIqAGG7U0KxTr8hJJU1p2ZQ2mXHmp4DhYP8N9SRuEKzaCPcSIcW7uj21jZqBigsLsNAXEzU8SPXZjmVQVtwQATPWeWyGW4GuJhjP4Q8o0.com',
'kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.CQ1oT5Uq3jJt6Uhy3VH9u3Gi5YhfZCvZVKgLlaXNFhVKB1zJxvunR7SJa.com.',
'cont-ains.h-yph-en-s.com',
'..com',
'ab..cc.dd',
'a.-bc.com',
'ab.cd-.com',
'-.abc.com',
'abc.-.abc.com',
'underscore_.example.com',
'',
-1,
array(),
'\r\n',
);
foreach ($values as $value) {
    var_dump(filter_var($value, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME));
}

var_dump(filter_var('_example.com', FILTER_VALIDATE_DOMAIN));
var_dump(filter_var('_example.com', FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME));
var_dump(filter_var('test_.example.com', FILTER_VALIDATE_DOMAIN));
var_dump(filter_var('test_.example.com', FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME));
var_dump(filter_var('te_st.example.com', FILTER_VALIDATE_DOMAIN));
var_dump(filter_var('te_st.example.com', FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME));
var_dump(filter_var('test._example.com', FILTER_VALIDATE_DOMAIN));
var_dump(filter_var('test._example.com', FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME));

echo "Done\n";
?>
--EXPECT--
string(11) "example.com"
string(71) "www.thelongestdomainnameintheworldandthensomeandthensomemoreandmore.com"
bool(false)
bool(false)
string(254) "kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.CQ1oT5Uq3jJt6Uhy3VH9u3Gi5YhfZCvZVKgLlaXNFhVKB1zJxvunR7SJa.com."
string(24) "cont-ains.h-yph-en-s.com"
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
string(12) "_example.com"
bool(false)
string(17) "test_.example.com"
bool(false)
string(17) "te_st.example.com"
bool(false)
string(17) "test._example.com"
bool(false)
Done

追加したいテストパターンを洗い出す

  • ホスト名のみ
    • www
    • localhost
  • ホスト名 + ドメイン名
  • ドメイン名のみ(ネイキッドドメイン(Zone Apex))
    • example.com(※既存のテストパターンに記述済みなので追加不要)
  • ホスト名 + ドメイン名が253文字以下
    • wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.www.tsunagi.me
    • w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.tsunagi.me
  • ホスト名 + ドメイン名が254文字以上
    • wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwww.tsunagi.me
    • w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.tsunagi.me
  • ラベルが63文字以下
    • wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww.tsunagi.me
  • ラベルが64文字以上
    • wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww.tsunagi.me
  • ラベル内に不正文字

phptファイルにテストパターンを追加する

% cp ext/filter/tests/056.phpt ext/filter/tests/056.phpt.orig
% diff ext/filter/tests/056.phpt ext/filter/tests/056.phpt.orig
26,37d25
< 'www',
< 'localhost',
< 'www.example.com',
< 'wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.www.tsunagi.me',
< 'w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.tsunagi.me',
< 'wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwww.tsunagi.me',
< 'w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.tsunagi.me',
< 'wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww.tsunagi.me',
< 'wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww.tsunagi.me',
< 'www.example,com',
< 'www.example com',
< 'www.examp!e.com',
72,83d59
< string(3) "www"
< string(9) "localhost"
< string(15) "www.example.com"
< string(253) "wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.www.tsunagi.me"
< string(252) "w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.tsunagi.me"
< bool(false)
< bool(false)
< string(74) "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww.tsunagi.me"
< bool(false)
< bool(false)
< bool(false)
< bool(false)

テストを実行する

※初回はビルド(コンパイル)が行われているようなのでかなり時間がかかります。
TESTS にphptファイルを指定することで、特定のテストを実行することが可能です。
Tests passed : 1 (100.0%) (100.0%) と表示されれば、追加したパターンも含めてすべてのテストが通っていることになります。

% make test TESTS='--show-diff ext/filter/tests/056.phpt'

Build complete.
Don't forget to run 'make test'.
・
・
・
=====================================================================
Running selected tests.
PASS filter_var() and FILTER_VALIDATE_DOMAIN [ext/filter/tests/056.phpt] 
=====================================================================
Number of tests :    1                 1
Tests skipped   :    0 (  0.0%) --------
Tests warned    :    0 (  0.0%) (  0.0%)
Tests failed    :    0 (  0.0%) (  0.0%)
Tests passed    :    1 (100.0%) (100.0%)
---------------------------------------------------------------------
Time taken      :    0 seconds
=====================================================================

TESTS--show-diff を指定しておくことで、テストに失敗した際に以下のようにどこで失敗したのかがわかります。

% make test TESTS='--show-diff ext/filter/tests/056.phpt'

Build complete.
Don't forget to run 'make test'.
・
・
・
=====================================================================
Running selected tests.
TEST 1/1 [ext/filter/tests/056.phpt]
========DIFF========
--
     string(3) "www"
     string(9) "localhost"
     string(15) "www.example.com"
021+ string(253) "wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.www.tsunagi.me"
021- string(252) "wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.wwwwwwwww.www.tsunagi.me"
     string(252) "w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.tsunagi.me"
     bool(false)
     bool(false)
--
========DONE========
FAIL filter_var() and FILTER_VALIDATE_DOMAIN [ext/filter/tests/056.phpt] 
=====================================================================
Number of tests :    1                 1
Tests skipped   :    0 (  0.0%) --------
Tests warned    :    0 (  0.0%) (  0.0%)
Tests failed    :    1 (100.0%) (100.0%)
Tests passed    :    0 (  0.0%) (  0.0%)
---------------------------------------------------------------------
Time taken      :    0 seconds
=====================================================================

=====================================================================
FAILED TEST SUMMARY
---------------------------------------------------------------------
filter_var() and FILTER_VALIDATE_DOMAIN [ext/filter/tests/056.phpt]
=====================================================================
make: *** [test] Error 1

参考URL

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1