CSSカスタムプロパティ色々便利なようです

ほぼ書き終わった記事を下書きで保存したら最初と最後だけになりました。
真ん中はどこへ行ったのでしょう?

株式会社イメージ・マジックの技術ブログ前回の担当のsoenoです。

最近CSSカスタムプロパティを触ることがあり、そのうちの機能で使わなかったところが気になったので コードと合わせて紹介します。


CSSカスタムプロパティとは?

CSSカスタムプロパティ(またはCSS変数)は、CSSで再利用可能なスタイル情報を格納し、管理するための仕組みです。
つまりscss環境を作らなくてもcssで変数が使えます。
また、scssの変数と合わせて使うこともできます。


CSSカスタムプロパティの使い方

通常のCSSプロパティと異なり、カスタムプロパティは--(ハイフン2つ)で指定します。 記載場所はcssで:root{}のカッコ内に指定すると(グローバルなスコープになるので) そのcssの読み込まれていれば別のcssからでも使えるようになります。 使うときはvar();で囲います。

指定して使用する例を以下に挙げます。
:root {
  --main-bg-color: blue;
}

#main{
  background:var(--main-bg-color);
}
上の例の#main{}の中でもCSSカスタムプロパティーを指定することができますが、その場合は#main{}の外では使えません。


javascriptからCSSカスタムプロパティの値を変更する

さて、本題です。 CSSカスタムプロパティで指定した値はjavascriptから変更することができます。 以下に例を挙げます。
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="utf-8">
    <title>カスタムプロパティデモ</title>
    <style type="text/css">
        :root {
            --h1Color: #e70d9e;
            --h2Color: #9e0de7;
            --h3Color: #350de7;
            --h4Color: #0d4be7;
            --h5Color: #0da2e7;
            --h6Color: #0de77a;
        }

        h1 {
            color: var(--h1Color);
        }

        h2 {
            color: var(--h2Color);
        }

        h3 {
            color: var(--h3Color);
        }

        h4 {
            color: var(--h4Color);
        }

        h5 {
            color: var(--h5Color);
        }

        h6 {
            color: var(--h6Color);
        }

        #stage{
            display: flex;
        }
        #inputArea {
            margin: 30px;
            width: 350px;
            flex:1;
        }
        #inputArea label{
            display: inline-block;
            width: 225px;
        }
        #inputTargetArea {
            display: flex;
        }
    </style>
</head>

<body id="stage">
    <div id="targetArea">
        <h1>h1 hello world</h1>
        <h2>h2 hello world</h2>
        <h3>h3 hello world</h3>
        <h4>h4 hello world</h4>
        <h5>h5 hello world</h5>
        <h6>h6 hello world</h6>
    </div>
    <div id="inputArea">
        <div id="inputTargetArea">
            <label for="targetChanger" name="targetChanger">何を変更するか選べます。</label>
            <select id="targetChanger">
                <option value="h1">h1</option>
                <option value="h2">h2</option>
                <option value="h3">h3</option>
                <option value="h4">h4</option>
                <option value="h5">h5</option>
                <option value="h6">h6</option>
            </select>
        </div>

        <div id="inputColorArea">
            <label for="colorChanger">何色に変更するかを選べます。</label>
            <input type="color" id="colorChanger" name="colorChanger" value="#cbcbcb" />
        </div>
    </div>

    <script language="javascript">
        document.getElementById("colorChanger").addEventListener("input", changeColor, false);
        function changeColor() {
            var targetTagName = document.getElementById("targetChanger").value;
            var newColor = this.value;
            document.documentElement.style.setProperty('--' + targetTagName + 'Color', newColor);
        }
    </script>
</body>
</html>
例は次のようになっています。

 ・cssカスタムプロパティでh1~h6の要素に文字色を指定。  ・セレクトボックスで各要素を指定できるように。  ・カラーピッカーで指定した色をCSSのカスタムプロパティーの変更で指定の要素に反映させる。

例では一対一なので良さがわかりにくいですが、変数で指定した個所すべてが変わります。 ですので指定したcssを引き継げばページをまたいだ指定や、そのユーザーのみのページテーマといった指定もできそうです。


結論

scss等使わないとできなかった変数での管理などがCSSカスタムプロパティでできるようになってます。 今回紹介はしていませんが、cssでなくjsで値を指定するなんてこともできます。 CSSカスタムプロパティ色々便利です。

Google Spreadsheet APIを使ってみる その1

はじめに

こんにちは、イメージ・マジックのもあいです。
GoogleのSpreadsheet APIを仕事で使用したので備忘録として残しておきます。

プロジェクトの作成

Googleアカウントでログインしておいて、Google Cloud コンソール の APIライブラリページ にアクセスし、プロジェクトの選択をクリックします


新しいプロジェクトをクリックします

プロジェクト名を入力して作成をクリック

しばらくするとプロジェクトが作成されます。

APIを有効にする

プロジェクトを作成した後、プロジェクトを選択すると下記の様になるので、Drive APIとSpreadsheet APIを有効にします。

Google Drive APIを選択して、有効にするをクリックします

Google Spreadsheet APIを選択して、有効にするをクリックします


認証情報の作成

Google Drive APIとGoogle Spreadsheet APIを有効にしたら認証情報を作成をクリックします

認証情報の作成は下記の様に選択をして次へボタンをクリックします

サービスアカウントIDを入力して作成して続行ボタンをクリック。サービスアカウントが作成できましたと表示されるので、完了ボタンをクリックします。

これでサービスアカウントが作成できました。
左ペインの認証情報をクリックして、サービスアカウント欄のサービスアカウントをクリックします。

キーをクリックします

鍵を追加をクリックし、新しい鍵を作成をクリックします

JSONを選択して作成をクリックします

jsonファイルがダウンロードされました。今後このファイルと画面に表示されているサービスアカウントのメールアドレス(testsample@testsample-398107.iam.gserviceaccount.com)を保存しておいてください。Driveでのファイルオーナーになります。

終わりに

今回はプロジェクト作成から認証情報の作成までとなります。認証情報作成で取得したjsonファイルの取扱には注意してください。間違ってもGitHub等のソースコード管理にコミットしてはいけません。

サーバ上のエラー発生行をブラウザからPhpStormで開く方法

こんにちは岡野です。
今回はPHPでの開発が楽になる方法を紹介します。最初の設定は面倒ですがメリットは大きいため、PhpStorm(もしくはIntelliJのPHPプラグイン)を使っている方はぜひ試してください。
   
  • 環境
    Windows
    IntelliJ IDEA 2023.2 + PHP Plugin
    Symfony(おそらく他のフレームワークでも対応可能)
    PhpStorm Protocol (最終編集2023-08-17)
  • インストール
  1. https://github.com/aik099/PhpStormProtocol のCodeボタンからzipをダウンロードする。  
  2. zip内の「PhpStorm Protocol (Win)」 を C:\Program Files\ へコピーする。  
  3. C:\Program Files\PhpStorm Protocol (Win)\run_editor.reg をダブルクリック。OK押下。  
  4. run_editor.jsを編集。上記PhpStormProtocol説明ページに載っている方法でうまくいかない場合は、editor変数を直接変更する。  
     
    editor = ‘”C:\\Users\\ユーザ名\\AppData\\Local\\Programs\\IntelliJ IDEA Ultimate\\bin\\idea64.exe”‘;
     
  5. Symfonyの設定を行う。 例は、サーバ:/opt/app/、ローカル:c:\git\app\symfony/というマッピングの場合。
(Symfony6.1以上の場合)
.env.localに以下を記述。
SYMFONY_IDE=phpstorm://open?file=%f&line=%l&/opt/app/>c:/git/app/symfony/
 
(Symfony6.0以下の場合)
framework.yaml内のframeworkにide要素を追加。
framework:
  ide: 'phpstorm://open?file=%%f&line=%%l&/opt/app/>c:/git/app/symfony/'
 
・実行
エラー発生時にファイルパスのリンクをクリックすると、該当箇所がIntelliJで開く。

Twigでも文字列連結

初めまして。石川です。
今日は、最近業務内でした新しい発見について共有させていただきます。

Twigで文字列連結するには

大したことではないのですが今までTwigでは文字列連結ができないと思って業務に取り組んでいました。
なぜなら、Twig触り始めたばかりの時に{{str1.str2}}という風に書いてエラーが出力されたからです。
その時に、きちんと調べなかったことが原因で、conntroller側で文字列連携した変数を作成してTwig側に渡すという風に切り抜けてきました。
しかし、今回きちんと調べてみると、{{str1~str2}}という風にすることで文字列連結できることを発見しました。

Twigで参照するには

ちなみに、ドットだと文字列連結ではなく参照が可能みたいです。
{% set array = {‘x’: 11, ‘y’:12} %}
{{ array.x }}
上記記載のようにすると参照できます。

Twigで変数展開するには

変数展開は{{ “aaa #{1 + 10} bbb”}}という風に、#{}で囲むことによってできます。 上記の結果は”aaa11bbb”となります。

最後に

Twig側で処理する方が、簡潔に書ける場合も多いのではないかと思うので、状況を見てTwig側に処理を書くのも良さそうです。 以上石川から共有させていただきました。

“0”はTRUEかFALSEか

 初めまして、陳です。今日は、数ヶ月前に文字列処理を行った際のミスと感想を少しご紹介したいと思います。

 文字列の値を判定する際には、有効な文字列であるかどうかや空でないかどうかを気にします。通常、渡された値がNULLか空の文字列であるかどうかをチェックします。

 そのとき、最初に思い浮かぶのはIF条件文ですよね。

 IF条件式は、プログラミングの中で最もよく使われる便利なものだと思います。条件を設定し、結果がTRUEかFALSEかによって処理を分岐させることができます。パラメータの値を基本的にチェックする際には、ほとんどの場合、欲しい値に合致しているかどうかを判断するためにIF条件式を使用します。

 FALSEかの判定に対して、最も簡単で便利な方法は、プログラミング言語におけるデータ値のTRUEかFALSEの判定を利用することです。よく知られているJavaScriptとして、FALSEと判定されるデータ値は以下の通りです:
  • JavaScript:
    – undefined
    – null
    – ブール値の false
    – 数値のゼロ: 0
    – 浮動小数点数のゼロ: 0.0
    – NaN (Not a Number)
    – 空の文字列: “”
 その時、私はそのような認識を持ち、PHPで空の文字列の判定をif(!$string)で処理していました。そして、私は間違えました。

 JavaScriptでは、文字列に対して、””(空文字列)はFALSEと判定されることを知っています。パラメータの値が空文字列でない場合、TRUEと判定されます。したがって、”a”や”0″のいずれもTRUEとなります。

 しかし、PHPの世界では少し異なります。FALSEと判定されるデータ値は以下の通りです:
  • PHP:
    – null
    – ブール値のfalse
    – 数値のゼロ: 0
    – 浮動小数点のゼロ: 0.0
    – 空の配列: []
    – 空の文字列: “”
    – 文字列”0″
 PHPでは、””(空文字列)以外にも、”0″という文字列もFALSEと判定されます。そのため、if(!$string)という条件だけでチェックすると、判定が誤ってしまうことがあります。

 文字列が空値でないのに、FALSEと判定されることに違和感を覚えたので、原因を調べてみました:

 PHPは、ウェブリクエストでの使用を前提として設計されており、頻繁に文字列の入力(URLパラメータやブラウザのフォームからのPOSTリクエストなど)を扱います。そのため、PHPは文字列を他の型に自動的にキャストします。

 これの簡単な例として、’1′ + ‘2’は3を返し、エラーや’12’などの他の解釈は行いません。同じロジックで、文字列’0’は数値0として使用することができます。

 ’0’は数値の0として使用できると言っていますが、数値の0は「空」です。PHPでは、「ゼロである」という特性を「文字列としての特性」よりも重視するため、’0’は「偽」と見なされます。

 要するに‘0’ == 0 == false もしくは (bool)’0′ === (bool)(int)’0′

(資料参考URL

 つまり、’0’という文字列は実は数値0として扱われ、そのためにFALSEと判定されるのです。
そのため、PHPで空文字列かどうかを判定したい場合には、次のような条件式を直接記述することが最善です。
  • $string === “”と空文字列を比較する
  • empty($string) というPHPの組み込み関数を使用して空値かどうかを判定する
  • strlen( $string ) === 0 と文字列の長さが0かどうかをチェックする

 以上、今回、皆さんとシェアしたい内容でした。

ファイルアップロードを伴うWebAPIの設計パターンを比べる

こんにちは、スズキです。 ファイルアップロードを伴うWebAPIを開発する機会がぼちぼちあるのですが、ファイルアップロード周りの方式をどんな設計にするかを迷いがちなので、考えを整理してみました。

方式1:multipart/form-dataを使う

ファイルアップロードの基本、multipart/form-dataをAPIリクエストに使う方式です。
  • 単純なAPIならコマンドでも比較的ポンと気軽に送信できるのが魅力
  • JSONベースのシステムから送信するときにリクエストを別途組み立てないといけないのが面倒

こういうときに採用すると良さそう

  • テキストデータが少なくファイルのやり取りがメインのAPIをつくりたいとき
  • コマンドベースで使えるようなシンプルなAPIをつくりたいとき

方式2:JSON+Base64エンコードを使う

application/jsonをAPIリクエストに使う方式です。ファイル自体のデータもBase64エンコードしてJSONデータの中に含めてしまいます。
  • JSONベースのシステムからAPIを使いやすいのが魅力
  • ファイルのエンコード・デコードの処理時間が余分にかかるのと、Base64エンコードすることでファイルサイズが増えるので通信時間が増える

こういうときに採用すると良さそう

  • ファイルサイズが小さくテキストデータのやり取りがメインのAPIをつくりたいとき
  • リクエストもレスポンスもすべてJSONでやり取りできるAPIをつくりたいとき

方式3:multipart/form-dataとJSONを使い分ける

開発するAPI群のうち、ファイルアップロード用APIだけmultipart/form-dataを使い、その他のAPIにはapplication/jsonを使う方式です。ファイルアップロード用APIでファイルを特定するためのキーを発行し、その他のAPIではそのキーを使ってファイルを指定します。
  • JSONベースのシステムから使いやすく、アップロードしたファイルを他のAPIで何度も使いまわしやすいのが魅力
  • ファイルアップロードが個別のAPIなため、APIのリクエスト回数が増える

こういうときに採用すると良さそう

  • サイズの大きいファイルと複雑なテキストデータのどちらも取り扱うAPIをつくりたいとき
  • アップロードしたファイルを何度も使いまわせるAPIをつくりたいとき

以上、どちらかというと私の備忘録な投稿でした。

文字列の途中の不要な文字列を正規表現で検知して消してみる

こんにちは。くろはです。 今回は意外と使う場面のありそう(個人的な感想)な”文字列途中の可変な不要箇所を正規表現を用いて消す”ということについて書こうかと思います。

背景


私はDBを操作する際のGUIアプリケーションとしてHeidiSQLというアプリケーションを使用しています。
HeidiSQLは単一テーブルから抽出したレコードをInsert文の形式でエクスポートできる機能があるため、
時々この機能を利用して開発環境からマスタデータをローカル環境に移してきて開発を行っています。
ただしここでそのままInsert文を実行してしまうと主キーとなっているID列が開発環境の状態のままテーブルに格納されてしまいます。
たいていは気にしなくてもよいのですがローカル環境も元々はいつぞやの時点の本番環境をコピーしたものなので開発環境のIDをそのまま使うと
自分の行っている改修とは無関係な動作を引き起こしかねない(=正しい結果が得られない)ことにつながるパターンがあったりします。
そこでid列を指定せずにレコードを挿入するとテーブル定義上は連番でIDを振ってくれるのでinsert文からID列と値の指定箇所を消してから挿入、といった作業を時々しています。
10行くらいなら「まぁ手作業でもよいか…」となりますがさすがにそれ以上は労力が見合ってくれません。 というわけで表題の正規表現で一気に指定箇所を置換してしまおうと思った次第です。

結論

このようなSQLが複数あったとしてID列とその値を1度に消します。
INSERT INTO `テスト` (`id`, `○○`, `△△`,`□□□`) VALUES (4401241, 'hoge', 'huga', 'hogehoge');
置換前と置換後の正規表現です。 置換前 (.+)id,(.+) VALUES ([0-9]*,(.+) 置換後 $1$2 VALUES ($3 置換した後のSQLは次のように変更されます。 このようなSQLが複数あったとしてID列とその値を1度に消します。
INSERT INTO `テスト` (`id`, `○○`, `△△`,`□□□`) VALUES (4401241, 'hoge', 'huga', 'hogehoge');
置換前と置換後の正規表現です。 置換前 (.+)id,(.+) VALUES ([0-9]*,(.+) 置換後 $1$2 VALUES ($3 置換した後のSQLは次のように変更されます。  
INSERT INTO `テスト` (`○○`, `△△`,`□□□`) VALUES ('hoge', 'huga', 'hogehoge');
無事ID列と値だけが消えました。  

考え方

正規表現における記号の意味等は割愛しますが置換前のパターン構造を文字で解説すると、 【文頭からidまでの任意の文字の繰り返し】 + 【`id`,】 + 【id,からVALUESまでの任意の文字の繰り返し】+【VALUES ( 【0~9の任意の数字の繰り返し+「,」】】+ 【以降文末までの任意の文字の繰り返し】 という感じです(逆に複雑か….?) 正規表現では”()”でくくると1つのグループとして評価されます。(=文字列とは判定されない) そのため「VALUES ( 」 として「 ( 」をエスケープしてあげないと正しくパターンを判定できません。 置換後の正規表現は結構シンプルで 【1つ目のグループに含まれる文字列】+【2つ目のグループに含まれる文字列】+【VALUES (】+ 【3つ目のグループに含まれる文字列】 というパターン構造になっています。 置換前のパターンの箇所で「”()”でくくるとグループとして評価されます」と書きましたが”()”にはもう一つ、後方参照という役割があります。 後方参照とはざっくりというとカッコ内のパターンに合致する文字列を記憶し、パターン内の変数の値として該当する文字列を返してくれます。 置換後の正規表現パターンの$1~$3がその変数にあたります。 これにより変更が不要な文字列をそのまま元の文字列から持ってくることができます。 青線が今回削除した部分、赤線がかっこでくくったり文字列をそのまま指定して新しく作る文字列として指定している部分です。こうやった方が分かりやすかったかも。 今回はIDの値にあたる部分がVALUES ( の後に来る文字列だったためVALUES ( をわざわざべた書きでパターンとしたけどもっと簡潔に書けたかもしれないと思えてきました。話が脱線しそうなので今回はここまでです。

終わりに

改めて見返すと正規表現のパターンの書き方って難しいけどどうパターンを組むかというのがパズルのようで楽しかったりするんですよね。ただカッコでネストしまくるとあっという間に迷宮の出来上がりなのでできるだけ簡潔に書けるように普段から意識していきたいですね。

PostmanのPre-requestって便利だなあ

こんにちわわ🐾。たにすぎです。先日APIのテストをする機会があってPostmanを利用したんですが、改めてPre-requestの機能が便利だな、と感じたので紹介します。

Postmanとは

https://www.postman.com/
Postman社が提供するAPIの開発用プラットフォームでリクエストや認証のテスト等を行えます。
Code snippetを使えばcURLやHTMLのコードにも変換してくれるので、Postmanのチームを共有していなくても他の人にリクエスト例を共有できるのでなにかと便利です。

Pre-requestって?

リクエストの前に決まった処理をしてくれる機能です。
APIを試すぞ、って時にパラメタにユニークなIDを設定しないといけなかったり、AのAPIの結果をBのAPIをリクエストに使用したい時など、手作業でパラメタ設定すると面倒な時にこのPre-requestが便利です。

ざっくり試し方

基本的なリクエストの方法は割愛します。
今回はあるAPIのリクエスト結果をPre-requestで取得して、その結果をAPIのリクエストに使います。

とりあえずENVを設定する

右上の目が付いた表みたいなアイコンを押してEnvironmentのAddをクリック
適当に変数セットの名前を入力して、Variablesに変数名を入れる

今回は環境で変わる(であろう)URLのメインの部分と1つ目のAPIの結果を入れるなんちゃらIdsを設定しています。

Pre-requestにリクエスト前の処理を書く

今回はAの結果でIDのリストのみが返ってくるのでこんな感じになりました。

const server = pm.environment.get("server"); //envからサーバー名を取得 
const xxxIdsUrl = "https://"+server+"/?limit=40";

pm.sendRequest(xxxIdsUrl, function (err, response) {
    pm.environment.set("xxxIds", response.json()); // なんちゃらIdsに結果をセット
});

envの値の取得方法が良くわからん、て場合もよく使う例が右側にSnippetsがあるので割と楽に書けました。

結果

リクエストURL横のSendを押してリクエストしてみます。

無事結果が取得できました。envのCurrent valueも更新されてます。

まとめ

使ってる方も多いかなと思いつつPostmanのPre-requestの機能を紹介しました。
Postmanで取得データのテストも書けたり、チームでコレクションを共有したりも出来るので、上手く使えば更に効率よく開発ができるんだろなと思います。
みんなで知見を共有しつつもっと活用したいですね……!

「R」を使ってみた

こんにちは、イメージマジック三浦です。最近はChatGPTで大騒ぎですが、今回は「R」を紹介します。

「R」とは

「R」は統計解析向けのプログラム言語・その開発実行環境を併せた総称です。統計学的な操作を行うためのメソッドが充実しています。特に計算式をプログラムに落とし込むような手間がなく、統計的な要件に対しては、とても使いやすいツールです。
プログラム言語と言いつつも、専門の書籍は数学関係の場所に置いてあることが多いです。

インストール

Rの公式サイトから「Download」の下にある「CRAN」をクリックすると、各国用のミラーサイトに遷移できます。遷移先のサイトから、Windows, macOS, Linux用のインストーラをダウンロードできるようになっています。 Rだけでも十分使えますが、RStudioを使うと便利です。画面表示は全部英語ですが、日本語を扱うことに問題はなく十分に使いやすいツールです。

サンプルプログラム

詳しい説明は省略しますが、参考として単回帰分析を行うコード例を出します。
data<-read.csv(
    "./_data/sample_data.csv",
    encoding = 'UTF-8',
    stringsAsFactors = F,
    header=T
)
x <- data$dataX
y <- data$dataY
result <- lm(y~x)
summary(result)
分析用のデータをきちんと準備すれば、これだけのコード量で単回帰分析を実行できます。仮に単回帰分析の導出式をプログラム言語で実装しようとすれば、サンプルコードの数倍くらい必要になるかもしれません。

計算の前後が大事

Rは、分析用データを準備すれば計算を実行して結果を返してくれますが、結果の品質はデータの準備度合いに依存します。例えば分析用データに以下のようなものが混ざっていれば、結果の精度が落ちてしまいます。
  • 全体的な傾向から逸脱しているデータがある
  • 分析に使うデータ量やパラメータが適切でない
  • データに抜けがある
このようなデータを除くために「前処理」という工程が存在し、「前処理」だけで1冊専門書が出るくらいの内容があります。 計算後にしても、予想通りの結果が得られたのか予想と異なる結果が得られたかを検証し、状況次第では分析の見直し等が必要になってきます。

まとめ

強力な機能を備えるRですが、出てきた結果を鵜呑みにせず、結果が本当に正しいかを吟味することが必要だと思います。そうできるように、これからも精進あるのみです。

ImageMagick脆弱性対応(パッチ)

こんにちは岡野です。
先日行った、画像処理ライブラリImageMagickの脆弱性対応を共有します。当社ではオリジナルプリントやMEET MY GOODSといったサービスで処理高速化のためリコンパイルしたImageMagickを使用しています。

脆弱性の概要

脆弱性(Metabase Qの報告
CVE-2022-44267:DoS攻撃
CVE-2022-44268:任意のファイル参照
ですが、不正なテキスト情報を埋め込んだPNGファイルをImageMagickが処理する際に発生する物でした。

脆弱性の対応案

・ImageMagickのバージョンアップ
ImageMagickを最新版へバージョンアップすれば解決するとのことでしたが、テストに時間が掛かるため他の方法を検討しました。

・画像データの修正
脆弱性の原因は前述の通り不正なテキスト情報ですので、ImageMagickへ画像ファイルを渡す前に不正なテキスト情報を除去する案です。PNG最適化ツールpngcrushで除去する方法をネットで見つけ試してみましたが除去処理に時間が掛かるためあきらめました(バージョンにより違うのかもしれませんが大きめの画像では10秒以上掛かることがありました)。

・ImageMagickのパッチ適用
脆弱性を修正するパッチをImageMagickのソースコードへ適用する案です。今回はこの案で対応しました。

パッチ適用の手順

今回はUbuntu用のパッチを流用しました。
https://launchpad.net/ubuntu/+source/imagemagick/8:6.9.7.4+dfsg-16ubuntu6.15
の「Available diffs」の箇所です。
但しとあるツイートに存在したPNGファイル
echo -en "P4\n1 1\nX" | pnmtopng -text <(echo 'fx:while(1,debug(hui=3)) 0') > payload.png
の脆弱性を防げなかったためパッチのif文
if ((LocaleCompare(key,"version") == 0) ||
    (LocaleCompare(key,"profile") == 0) ||
    (LocaleCompare(key,"width") == 0))
へ「fx:」を無効化する
    (LocaleNCompare(key,"fx:",3) == 0) ||
を追加しました(ImageMagickのバージョンによっては再現しなさそうでした、おそらくこのissue)。

まとめ

残念ながらImageMagickの脆弱性は今後も発見されると思いますので、バージョンアップを容易にしておく必要性を感じました。今後はバージョンアップ用の自動テストケースを準備しようと思います。