Heirloom Toolchest tr:マルチバイト文字を含むコレクションのサプリメントを削除中にエラーが発生しましたか?

Heirloom Toolchest tr:マルチバイト文字を含むコレクションのサプリメントを削除中にエラーが発生しましたか?

使ってみようtrコマンドは以下から来ます。家宝ツールボックス克服する現在の制限~のコアツール-dc「任意」ジェネレータでマルチバイト文字を「ポンプ」(オプションを使用)できるように実装されています(/dev/urandom)ターミナルまで。これがすでにあることは注目に値する。コンパイル済みソースから開始アーチバンAURの使用に失敗した後バージョン

これを簡単にするために文字(☠)を選択し、対応する8進数値を理解してみましょう。これは、ツールボックスに対して次のように表現する必要があるためですtr

echo '☠' | hexdump -b            # -b for octal
0000000 342 230 240 012                                                
0000004
echo -e '\0342\0230\0240'        # uses the "0nnn" format, make sure it prints

8進値の表現方法に違いがあります吹くそしてecho 組み込み0nnn) ここのツールボックスtr():

文字 "\" の後に 1、2、3 個の 8 進数字が続く場合、その数字でバイトコードが提供される文字を表します。マルチバイト文字は、8進バイトシーケンスで指定できます。

やってみようこの-dcオプションは単にSET1の補数を削除します。セットを指定すると、そのセットの要素を含まない標準入力のすべての項目が削除されます。

echo '012345' | /usr/5bin/tr -dc '456'   #sanity check
45                                       #all good

今これらは:

echo -e '\0342\0230\0240' | /usr/5bin/tr -dc '\342\230\240'
echo -e '☠' | /usr/5bin/tr -dc '☠'

どちらもone(1)☠を印刷する必要があります。それ以外の場合、最終的に次の文字(より多くの文字)はすべて同じエラーを生成します。

/usr/5bin/tr -dc '\342\230\240' < /dev/urandom

*** Error in `/usr/5bin/tr': double free or corruption (!prev): 0x0000000000d24420 ***

実際には、入力とSET1の両方に選択した文字が含まれるたびにエラーが発生し、と表示されます-dc。この動作はシステム全体でも同じです。SysV 3rd、4th、Posix、Posix2001またはucb(BSD)ツールボックスに提供されるコマンドのバージョンです。時にはtr -dc '1' < /dev/urandom適切なsegfaultや数行の出力が表示されることがあります。

Error in `/usr/5bin/tr': realloc(): invalid pointer: 0x00007f93ee284010 ***
======= Backtrace: =========
/usr/lib/libc.so.6(+0x73f8e)[0x7f93ee338f8e]
/usr/lib/libc.so.6(+0x7988e)[0x7f93ee33e88e]
/usr/lib/libc.so.6(realloc+0x1c8)[0x7f93ee342918]
/usr/5bin/tr[0x401a74]
/usr/5bin/tr[0x400e93]
/usr/lib/libc.so.6(__libc_start_main+0xf0)[0x7f93ee2e5000]
/usr/5bin/tr[0x400f63]
======= Memory map: ========
00400000-00403000 r-xp 00000000 08:21 1579535                            /usr/5bin/tr
00602000-00603000 rw-p 00002000 08:21 1579535                            /usr/5bin/tr
0067a000-006bc000 rw-p 00000000 00:00 0                                  [heap]
7f93edc6e000-7f93edc84000 r-xp 00000000 08:21 1448153                    /usr/lib/libgcc_s.so.1
7f93edc84000-7f93ede83000 ---p 00016000 08:21 1448153                    /usr/lib/libgcc_s.so.1
7f93ede83000-7f93ede84000 rw-p 00015000 08:21 1448153                    /usr/lib/libgcc_s.so.1
7f93ede84000-7f93ee2c5000 rw-p 00000000 00:00 0 
7f93ee2c5000-7f93ee469000 r-xp 00000000 08:21 1440453                    /usr/lib/libc-2.19.so
7f93ee469000-7f93ee669000 ---p 001a4000 08:21 1440453                    /usr/lib/libc-2.19.so
7f93ee669000-7f93ee66d000 r--p 001a4000 08:21 1440453                    /usr/lib/libc-2.19.so
7f93ee66d000-7f93ee66f000 rw-p 001a8000 08:21 1440453                    /usr/lib/libc-2.19.so
7f93ee66f000-7f93ee673000 rw-p 00000000 00:00 0 
7f93ee673000-7f93ee694000 r-xp 00000000 08:21 1440340                    /usr/lib/ld-2.19.so
7f93ee6eb000-7f93ee874000 r--p 00000000 08:21 1448356                    /usr/lib/locale/locale-archive
7f93ee874000-7f93ee877000 rw-p 00000000 00:00 0 
7f93ee891000-7f93ee893000 rw-p 00000000 00:00 0 
7f93ee893000-7f93ee894000 r--p 00020000 08:21 1440340                    /usr/lib/ld-2.19.so
7f93ee894000-7f93ee895000 rw-p 00021000 08:21 1440340                    /usr/lib/ld-2.19.so
7f93ee895000-7f93ee896000 rw-p 00000000 00:00 0 
7fffed79c000-7fffed7bd000 rw-p 00000000 00:00 0                          [stack]
7fffed7e9000-7fffed7eb000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

これは私の部分のコンパイルエラーを意味しますか、それとも正しく使用しませんか?


貢献として修理する私たちは:

echo -e '\0342\0230\0240' | /home/me/bin/trsc -dc '\342\230\240'
echo -e '☠' | /home/me/bin/trsc -dc '☠'

私たちがそうしなければならないように!しかし:

/home/me/bin/trsc -dc '\342\230\240' < /dev/urandom

選択したキャラクターが出力されないことは依然として謎です...

ベストアンサー1

私はそれを見たことがない。間違い。努力する:

--- tr.c        6 Sep 2005 23:04:11 -0000       1.10
+++ tr.c        30 May 2014 09:46:33 -0000
@@ -291,7 +291,6 @@
                if(c<ccnt) code[c] = d;
                if(d<ccnt && sflag) squeez[d] = 1;
        }
-       free(vect);
        while((d = next(&string2)) != NIL) {
                if(sflag) squeez[d] = 1;
                if(string2.max==NIL && (string2.p==NULL || *string2.p==0))

(これは数ヶ月前の簡単な外観であり、このパッチを介して前進できますが、それが正しいことを保証することはできません。Applyを使用してくださいpatch -l。)

これで/dev/urandomストリームも提供されます。バイト。 UTF-8では、すべてのバイトシーケンスが有効な文字にマッピングされるわけではありません。たとえば、0x41 0x81 0x41は0x800x81なので無効であるため、>=0x80バイトを超える2バイト以上のシーケンスとしてのみ表示できます。

☠の補足文字セットに含まれていないため削除されないため、無効なバイトですtr

より良い方法は次のとおりです。

recode ucs-2..u8 < /dev/urandom | tr -cd ☠

Ucs-2はU + 0000からU + FFFFまでの文字で、各文字は2バイトにエンコードされ、/dev/urandomucs-2文字ストリームに似ています。 (ただし、U+10000からU+10FFFFまでの文字が欠落しています。)

しかし、これにはまだ含まれています。D800..DFFFプロキシペア範囲 これはmbrtowc(3)息をのむようなものです(少なくとも私のバージョンのlibcでは)。

これらのコードポイントはUTF-16エンコーディング用に予約されています。たとえば、d800dc00はU + 10000のUTF-16BEエンコーディングですが、U + D800文字またはU + DC00はありません。これらの文字のUTF-8エンコーディングも意味がありません(隣接する場合でも)。

したがって、まず除外する必要があります。

perl -ne 'BEGIN{$/=\2;binmode STDOUT,":utf8"}
          $c = unpack("n",$_); if ($c < 0xd800 || $c > 0xdfff) {
            no warnings "utf8"; print chr($c)
          }' < /dev/urandom | tr -cd ☠

目標がUTF-8でエンコードされた任意のUnicode文字ストリームを取得する場合は、許容範囲(0..0xd7ff、0xf000..0x10ffff)内で任意のコードポイントを取得してUTF-8に変換することをお勧めします。に基づいている場合は、/dev/urandom各コードポイントに3バイト(24ビット)を使用できます。

perl -ne 'BEGIN{$/=\3;binmode STDOUT,":utf8"}
          $c = unpack("N","\0$_") * 0x10F800 >> 24;
          $c+=0x800 if $c >= 0xd800;
          do {no warnings "utf8"; print chr($c)}' < /dev/urandom |
  tr -cd ☠

おすすめ記事