PODSTAWA i zachowanie powrotu karetki


11

Mam jedno szybkie pytanie.
Czy to normalne, że bash (używam 4.4.11) nie wyświetla linii / tekstu oddzielonego / zakończonego zwykłym \r?

Byłem trochę zaskoczony tym zachowaniem:

$ a=$(printf "hello\ragain\rgeorge\r\n")
$ echo "$a"
george

Ale tekst „witaj ponownie” wciąż tam jest, w jakiś sposób „ukryty”:

$ echo "$a" |od -w32 -t x1c
0000000  68  65  6c  6c  6f  0d  61  67  61  69  6e  0d  67  65  6f  72  67  65  0d  0a
          h   e   l   l   o  \r   a   g   a   i   n  \r   g   e   o   r   g   e  \r  \n

A gdy tylko gramy w bash, wszystko jest w porządku .... Ale czy to potencjalne zagrożenie bezpieczeństwa? Co jeśli zawartość zmiennej „a” pochodzi ze świata zewnętrznego i zawiera „złe polecenia” zamiast po prostu cześć?

Kolejny test, tym razem trochę niepewny:

$ a=$(printf "ls;\rGeorge\n")
$ echo "$a"
George
$ eval "$a"
0                   awkprof.out       event-tester.log  helloworld.c      oneshot.sh         rightclick-tester.py  tmp                    uinput-simple.py
<directory listing appears with an error message at the end for command George>

Wyobraź sobie ukryty rmzamiast ukrytego ls.

To samo zachowanie przy użyciu echa -e:

$ a=$(echo -e "ls;\rGeorge\r\n"); echo "$a"
George

Czy to ja robi coś złego ...?

Odpowiedzi:


20

Twoje echo "$a"odbitki „cześć”, następnie wraca na początek linii (co jest tym, co \rrobi), drukuje „ponownie”, wraca ponownie, drukuje „george”, wraca ponownie i przechodzi do następnej linii ( \n). To wszystko jest całkowicie normalne, ale jak wskazuje chepner , nie ma to nic wspólnego z Bash: \ri \nsą interpretowane przez terminal, a nie przez Bash (dlatego otrzymujesz pełną moc wyjściową, gdy potokujesz polecenie od).

Możesz to lepiej zobaczyć za pomocą

$ a=$(printf "hellooooo\r  again,\rgeorge\r\n")
$ echo "$a"

ponieważ pozostawi to koniec zastąpionego tekstu:

georgen,o

Tak naprawdę nie można tego użyć do ukrywania poleceń, tylko ich danych wyjściowych (i tylko wtedy, gdy możesz być pewien, że zastąpisz je wystarczającą liczbą znaków), chyba że używasz evaltak, jak pokazano (ale używanie nie evaljest ogólnie zalecane). Bardziej niebezpieczną sztuczką jest używanie CSS do maskowania poleceń przeznaczonych do kopiowania i wklejania ze stron internetowych.


Dość jasne, dzięki. Miałem szczęście / nieszczęście, że użyłem ostatniego słowa w moim teście, mogąc całkowicie zastąpić poprzednie dwa słowa.
George Vasiliou,

2
Zauważ jednak, że tak naprawdę nie ma to nic wspólnego bash; od terminala zależy „wyświetlanie” znaku powrotu karetki lub wyświetlanie znaków zastąpionych. Na przykład idealnie byłoby, gdyby terminal wyświetlał się -\r|jako coś przypominającego znak plus, a nie tylko potok.
chepner,

@chepner Dobrze wiedzieć! Dzięki za udostępnienie. Myślałem, że to tylko bzdura.
George Vasiliou,

@GeorgeVasiliou Nie, bashpo prostu zapisuje bajty do pliku; to kto czyta te bajty, je interpretuje.
chepner,

Nitpick:, printfktóry jest wbudowanym poleceniem bash (chociaż istnieje również jako samodzielny plik wykonywalny), interpretuje \r(sekwencję dwóch bajtów: 0x5ci 0x72zwraca zwrot karetki (pojedynczy bajt:) 0x0d. Następnie tak, terminal interpretuje bajt 0x0dw szczególny sposób, ale to nie interpretuje oryginalny łańcuch \r.
Suzanne Dupéron

6

W świecie uniksowym powrót karetki (powszechnie kodowany jak \rw językach programowania) jest niczym niezwykłym znakiem kontrolnym. Znaki powrotu karetki mogą znajdować się w wierszu tekstu, podobnie jak każdy inny znak oprócz przejścia do nowego wiersza (zwanego także nowym wierszem ), który oznacza koniec wiersza.

W szczególności, w skrypcie bash, znak powrotu karetki jest zwykłym składnikiem słowa, takim jak litery i cyfry. Jakikolwiek efekt specjalny powrotu karetki pochodzi z terminala, a nie z powłoki.

Zwrot karetki jest znakiem kontrolnym . Gdy drukujesz go na terminalu, zamiast wyświetlać glif , terminal wykonuje jakiś efekt specjalny. W przypadku powrotu karetki efektem specjalnym jest przesunięcie kursora na początek bieżącej linii. Zatem jeśli wydrukujesz linię, która zawiera znak powrotu karetki na środku, efekt jest taki, że druga połowa zostanie zapisana na pierwszej połowie.

Kilka innych znaków kontrolnych ma efekty specjalne: znak cofania przesuwa kursor w lewo o jedną pozycję. Dzwonek powoduje, że terminal emituje dźwięk lub w inny sposób przyciąga uwagę użytkownika. Znak ucieczki rozpoczyna sekwencję ucieczki, która może mieć różnego rodzaju efekty specjalne.

Jeśli wyświetlasz niezaufane dane wyjściowe, musisz wyszorować lub usunąć znaki kontrolne. Powraca nie tylko karetka, ale także kilka innych, w szczególności postać ucieczki, która może powodować różnego rodzaju złe efekty. Zobacz Czy „przechwytywanie” pliku może stanowić potencjalne zagrożenie bezpieczeństwa? i Jak uniknąć ataków sekwencji ucieczki na terminalach? po więcej na ten temat.


0

Możesz wyświetlić powroty karetki w zmiennej bash, używając printffunkcji z %qformatem.

$ TESTVAR="$(printf ' Version: 1 \r Build: 20180712 \r Test: 1324')"

$ printf %q $TESTVAR
Version:1$'\r'Build:20180712$'\r'Test:1324

Źródła i dalsze czytanie:

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.