とんちむ日記

RubyとJavaScriptと猫が好きです

Rubyの正規表現に潜む罠!!

現在のプロジェクトでmodelのバリデーションを正規表現で行う機会がありました。

Javascriptなんかでは最近よく触っていたので正規表現には特に抵抗なかったんですが・・・思わぬ罠に引っかかってしまいました。

例えばこんな /^[0-9]+$/ というようなよく見る整数の正規表現なんですが・・・このまま動かそうとすると例外発生!!

The provided regular expression is using multiline anchors (^ or $), which may present a security risk. Did you mean to use \A and \z, or forgot to add the :multiline => true option?

まさか正規表現で例外がでるとは思ってなかったのでぽかんとしていました。

上記の意味ですが、「与えられた正規表現複数行アンカー(^か$)を使ってるからエラー出たよ、セキュリティ的な危険があるけど\A と\zを使うつもりだったのかそれとも複数行オプションをつけ忘れたのかい?」

まぁこんな感じです、てきとうな訳ですが細かいことは気にしない気にしない。

Rubyは他の言語と違い、改行を含んだ値が渡されると、その値のどこか一つの行にマッチすれば他は気にしないという謎仕様なのです。
^と$は通常は入力された値の全体の先頭と末尾を表しますが、Rubyの場合は若干異なり、行の先頭と末尾になるのです。

じゃあどうするかというと、メッセージどおりに^を\Aに$を\zに変更するだけでOKです。または multiline: trure をオプションで追加して

validates :hogehoge , format: { with:/^pattern$/, multiline: true }

とすればOKです。multilineオプションをつけることで他の言語と同じような挙動になります。


詳しくはRails セキュリティガイド の6.6正規表現に書いてあります。

皆さんもどうか罠には気を付けて…まぁそのままだと例外出るから大丈夫だろうけど。

Angularで起こった怪奇!?

ありのまま、今日起こった事を話すぜ・・・

 

input numberに999999999999999934464以上の数値を入力すると /^[0-9]*$/(0以上の数字ならOK)のパターンにマッチせずにエラーメッセージが表示されたんだ。

 

な・・・何を言ってるかわからねーと思うがおれも何をされたのか分からなかった・・・

 

 

という恐ろしい現象!?真夏の怪奇を味わいました。まぁこれなんとか原因突き止めたんですが。

 

まず999999999999999934464という数字をググってみると何やら英語のサイトを発見・・・するとどうやら999999999999999934464以上の数値は見た目にはわからないが指数表記になっている模様。

 

指数表記ってのは電卓とかでも大きな数になると1e+1とか出ますよね、あれのことです。

 

Angularのng-patternを使っていた時に発生したんですが、ほかの環境では再現されずAngularのバージョンか、またはコントローラーとかの他の部分が悪さしてるのかもしれません。(だからこの記事が役に立つことはあまりないような気がする・・・)

Angularのバージョンの問題でした。最新バージョンでは解決しているようです。

 

 

そもそもなんで$error.numberを使わないの?と思われそうですが、使ってるんですよねすでに、それだけだと小数に対応できないんですよ。

 

指数表記を数字に直してくれるような機能ないかなーと思っていたらJavaScriptのNumber.prottype.toFixed()というメソッドを発見!

 

これで直ると思いきや・・・「number が 1e+21 【訳注: e+21 は 10 の21乗】 より大きい場合、このメソッドは単純に Number.toString() を呼び出し、指数表記での文字列を返します。(MDNより引用)」

 

つ、使えねぇ・・・なぜって999999999999999934464は1e+21だからです。

 

仕方なく指数表記も加えたパターンを作りましたとさ・・・。

 

それがこちら

/^\d*((\.\d+)e\+\d+)$/

 

通常の数字でも、指数表記でも対応できます!マイナスなどにはちょっと手を加えてくださいね。

 

普通に文字として指数表記入力したらマッチしそうですがその場合は$error.numberが最初に弾いてくれるので問題ないですw

 

--追記--

よくよく考えたら$error.numberがほとんど弾いてくれるので小数点だけを省けばいい話でした・・・。

なので  /^[^\.]*$/  これでOKです。

初めて学ぶプログラミング言語は何がいいか?

結論から言えば何したいかによるってことになりますが、まぁ・・・もうちょっと掘り下げていきましょう。

 

新米エンジニアの僕は今でこそ一応はプログラミングができるようになりましたが、それは今の会社の研修を受けてしっかりと指導してもらったり、一緒に励む同期の仲間がいたりしたからこそできたものだと思います。

 

入社するまでプログラミングに憧れてはいたものの、何度も挫折してばかりでした。

小学生の時にBASICを勉強しようとして、挫折。まぁこれは無理がありましたね。

次に高校かな?Perl&CGIを勉強しようとして挫折。当時あったブラウザゲームをいじりたかったんですよね。

最後にObjective-CこれはiPhoneアプリを作りたかったから。まぁ少しばかり動きましたがなんで動くのかよくわからないままだったので全く身につきませんでした。

 

どれもうまくいきませんでした。最初の二つは理解力不足のせいが大きいですね。最後の一つは選んだ本が良くなかった気がしますね。ものによりますが作りながら学ぶ系の書籍はプログラミング未経験者はやめといたほうがいいと思います。

 

で、本題何ですが、まずプログラミングをやりたい人って色々いますよね? その目的次第だと思うんです。例えば将来エンジニアになりたいという人。そんな人は言語の勉強よりもまず業界のこと知るべきだと思います。一口にエンジニアと言ってもいろいろあるし、どの分野ではどんな言語が主流なのかとか、どんなものを作りたいのか。Web系なのか組み込みなのかで全然使う言語は違ってきます。まぁいろんな分野でも使える言語もあるんですが。

 

アプリを作りたいという人だったら限られてきますね、iOSアプリならswiftだったり、Objective-cだったりですね。Objective-CJavaよりも歴史が長いらしいですがswiftの方が後発なだけあって扱い易いという話をよく聞きます。

AndroidアプリならJavaですね(とはいえ今後これも動向が変わるかもしれません)、アプリはHTML5JavaScriptを使って作るという方法もあるそうです。そのほうが環境構築とか考えると手軽かもしれません。

 

個人的にはJavaやCのようなちょっと堅めの言語がいいんじゃないかと思います。まぁ最初で躓いたりする可能性も大ですが・・・。今はRubyを仕方なく触っているのですが、緩いしなんか目茶苦茶なこともできるしで、Rubyキモイと思っていますw

いきなり型宣言なしのゆるゆるの言語からだといざJavaとかに移った時にめんどくささ半端ないと思います。(慣れれば静的型そのものは便利なんですが)

 

マルチな環境で使えるということも考えるとやっぱしJavaがいいんじゃないでしょうか。Web界隈でもまだまだ人気の言語だし。今後もしばらくは廃れなさそうです。ただし、どの言語もやりたいことを形にできるようになるまで時間がかかります。これが何の役に立つの? って気持ちは始めはずーっとついてくるでしょうがいずれ全部が繋がっていくはずです。頑張っていきましょう。