Connector/JのSQLインジェクション脆弱性 つづき

以前のエントリで紹介したMySQLJDBCドライバConnector/J 5.1.7のSQLインジェクション脆弱性ですが、ようやくパッチができたようです。

public void setString(int parameterIndex, String x) throws SQLException {
    …
    for (int i = 0; i < stringLength; ++i) {
        …
        case '\u00a5':
        case '\u20a9':
        // escape characters interpreted as backslash
            if(charsetEncoder != null) {
                CharBuffer cbuf = CharBuffer.allocate(1);
                ByteBuffer bbuf = ByteBuffer.allocate(1);
                cbuf.put(c);
                cbuf.position(0);
                charsetEncoder.encode(cbuf, bbuf, true);
                if(bbuf.get(0) == '\\') {
                    buf.append('\\');
                }
            }
            // fall through
        default:
            buf.append(c);
        }
    }

性能重視のブラックリスト形式ですね。円記号(U+00A5)と韓国のウォン記号(U+20A9)に対してのみ、変換後の文字がバックスラッシュになるかどうかをチェックしています。また、変換後がバックスラッシュにならないキャラクタセットの組み合わせではcharsetEncoderがあらかじめnullになっており、チェックルーチンを通らないようになっています。そのため今回の脆弱性と無関係な環境においては、性能劣化が低く抑えられています。
私はUnicodeに特別詳しいわけではないので、ブラックリストに漏れがないかとか、今後変換対象の文字が増えたらどうするのか、とかは分かりません。すいません。何かお気づきの点があれば、上記バグレポートに早めにコメントをつけていただければと思います。
他の多くのRDBMSのように、SQLバインド機構として最初からServer-Side PreparedStatementしかないのであれば何も起こらなかったのですが、MySQLは歴史的にClient-SideのPreparedStatementが先にできてしまったので苦労していますね。それにBrian AkerがあまりServer-Side PreparedStatementに興味なさそうですしね…。