समस्या क्या है
सबसे पहले, कई उपयोगिताओं के लिए, आपके पास फ़ाइल नाम के साथ शुरू होने वाला मुद्दा होगा -
। जब में:
sh -c 'inline sh script here' other args
अन्य आर्गों को पारित किया जाता है inline sh script
; perl
समकक्ष के साथ ,
perl -e 'inline perl script here' other args
अन्य आर्ग और अधिक विकल्प के लिए के लिए स्कैन किए पर्ल पहले, इनलाइन स्क्रिप्ट के लिए नहीं। उदाहरण के लिए, यदि -eBEGIN{do something evil}
वर्तमान निर्देशिका में एक फ़ाइल है ,
perl -ne 'inline perl script here;' *
(साथ या बिना -n
) कुछ बुराई करेगा।
अन्य उपयोगिताओं की तरह, इसके लिए चारों ओर का काम अंत-विकल्प मार्कर ( --
) का उपयोग करना है:
perl -ne 'inline perl script here;' -- *
लेकिन फिर भी, यह अभी भी खतरनाक है और इसके <>
द्वारा उपयोग किए गए ऑपरेटर के लिए नीचे है -n
/ -p
।
मुद्दे को perldoc perlop
प्रलेखन में समझाया गया है।
उस विशेष ऑपरेटर का उपयोग इनपुट की एक पंक्ति (एक रिकॉर्ड, रिकॉर्ड डिफ़ॉल्ट रूप से रेखाएं) को पढ़ने के लिए किया जाता है, जहां वह इनपुट बारी-बारी से पारित किए गए प्रत्येक तर्क से आ रहा है @ARGV
।
में:
perl -pe '' a b
-p
while (<>)
कोड (यहां खाली) के चारों ओर एक लूप का अर्थ है ।
<>
पहली बार खुलेगा a
, एक समय में एक लाइन रिकॉर्ड करें जब तक कि फ़ाइल समाप्त न हो जाए और फिर खुले b
...
समस्या यह है कि, फ़ाइल को खोलने के लिए, यह पहले, असुरक्षित रूप का उपयोग करता है open
:
open ARGV, "the file as provided"
उस रूप के साथ, यदि तर्क है
"> afile"
, यह afile
लेखन मोड में खुलता है,
"cmd|"
, यह चलता है cmd
और इसे आउटपुट पढ़ता है।
"|cmd"
, आप इनपुट के लिए लिखने के लिए एक धारा खुला है cmd
।
उदाहरण के लिए:
perl -pe '' 'uname|'
नामक फ़ाइल की सामग्री का उत्पादन नहीं करता है uname|
(पूरी तरह से मान्य फ़ाइल नाम btw), लेकिन uname
कमांड का आउटपुट ।
यदि आप चला रहे हैं:
perl -ne 'something' -- *
और किसी ने rm -rf "$HOME"|
वर्तमान निर्देशिका में (फिर एक पूरी तरह से वैध फ़ाइल नाम) नामक एक फ़ाइल बनाई है (उदाहरण के लिए क्योंकि वह निर्देशिका एक बार दूसरों द्वारा लिखी गई थी, या आपने एक डॉगी संग्रह निकाला है, या आपने कुछ डॉगी कमांड चलाया है, या किसी अन्य सॉफ्टवेयर में एक और भेद्यता का शोषण किया गया था), तो आप बड़ी मुसीबत में हैं। जिन क्षेत्रों में इस समस्या से अवगत होना महत्वपूर्ण है, वे सार्वजनिक क्षेत्रों में स्वचालित रूप से टूल प्रोसेसिंग फाइल हैं /tmp
(या ऐसे उपकरण जिन्हें टूल कहा जा सकता है)।
फ़ाइलें बुलाया > foo
, foo|
, |foo
एक समस्या है। लेकिन कुछ हद तक < foo
और foo
ASCII रिक्ति वर्ण (अंतरिक्ष, टैब, newline, cr ...) के साथ-साथ उन फ़ाइलों को संसाधित नहीं किया जाएगा या गलत एक हो जाएगा।
यह भी सावधान रहें कि कुछ मल्टी-बाइट कैरेक्टर सेट (जैसे ǖ
BIG5-HKSCS) में कुछ अक्षर बाइट 0x7c के एन्कोडिंग में समाप्त होते हैं |
।
$ printf ǖ | iconv -t BIG5-HKSCS | od -tx1 -tc
0000000 88 7c
210 |
0000002
तो उस चारसेट का उपयोग करने वाले स्थानों में,
perl -pe '' ./nǖ
उपयोगकर्ता के स्थान में उस फ़ाइल नाम की व्याख्या करने की कोशिश नहीं करेगा ./n\x88
जैसा कि कमांड को चलाने की कोशिश perl
करेगा !
कैसे ठीक करें / आसपास काम करें
AFAIK, ऐसा कुछ भी नहीं है जिसे आप perl
एक बार और सभी सिस्टम-वाइड के असुरक्षित डिफ़ॉल्ट व्यवहार को बदलने के लिए कर सकते हैं ।
सबसे पहले, समस्या केवल फ़ाइल नाम के प्रारंभ और अंत में वर्णों के साथ होती है। तो, जबकि perl -ne '' *
या perl -ne '' *.txt
एक समस्या है,
perl -ne 'some code' ./*.txt
क्योंकि सभी तर्कों अब के साथ शुरू नहीं कर रहा है ./
और में अंत .txt
(ऐसा नहीं -
, <
, >
, |
, अंतरिक्ष ...)। अधिक आम तौर पर, ग्लब्स के साथ उपसर्ग करना एक अच्छा विचार है ./
। यह भी बुलाया फ़ाइलों के साथ समस्याओं से बचा जाता है -
या -
कई अन्य उपयोगिताओं के साथ शुरू होता है (और यहां, इसका मतलब है कि आपको अंत-विकल्प ( --
) मार्कर की आवश्यकता नहीं है)।
मोड -T
चालू करने के लिए उपयोग करने taint
से कुछ हद तक मदद मिलती है। यह दुर्भावनापूर्ण फ़ाइल (केवल >
और |
मामलों, नहीं <
या व्हॉट्सएप के लिए) का सामना होने पर कमांड को रद्द कर देगा ।
इस तरह के आदेशों का उपयोग करते समय यह उपयोगी होता है क्योंकि यह आपको सचेत करता है कि कुछ गड़बड़ चल रहा है। हालांकि, कुछ स्वचालित प्रसंस्करण करते समय यह वांछनीय नहीं हो सकता है, क्योंकि इसका मतलब है कि कोई व्यक्ति केवल फ़ाइल बनाकर उस प्रसंस्करण को विफल कर सकता है ।
आप हर फ़ाइल पर कार्रवाई करने, उनके नाम की परवाह किए बिना चाहते हैं, तो आप उपयोग कर सकते हैं CPAN पर मॉड्यूल (दुर्भाग्य से आमतौर पर डिफ़ॉल्ट रूप से स्थापित नहीं)। यह एक बहुत छोटा मॉड्यूल है जो करता है:ARGV::readonly
perl
sub import{
# Tom Christiansen in Message-ID: <24692.1217339882@chthon>
# reccomends essentially the following:
for (@ARGV){
s/^(\s+)/.\/$1/; # leading whitespace preserved
s/^/< /; # force open for input
$_.=qq/\0/; # trailing whitespace preserved & pipes forbidden
};
};
मूल रूप से, यह @ARGV " foo|"
को उदाहरण के लिए बदलकर सुरक्षित करता है "< ./ foo|\0"
।
आप BEGIN
अपने perl -n/-p
आदेश में एक बयान में ऐसा कर सकते हैं :
perl -pe 'BEGIN{$_.="\0" for @ARGV} your code here' ./*
यहां हम इसे उस धारणा पर सरल करते हैं ./
जिसका उपयोग किया जा रहा है।
कि (और का एक पक्ष प्रभाव ARGV::readonly
), हालांकि वह यह है कि $ARGV
में your code here
पता चलता है कि NUL चरित्र अनुगामी।
अद्यतन 2015-06-03
perl
v5.21.5 और इसके बाद के संस्करण में एक नया <<>>
ऑपरेटर होता है जो इस तरह के व्यवहार करता है <>
सिवाय इसके कि यह उस विशेष प्रसंस्करण को नहीं करेगा । तर्क केवल फ़ाइल नाम के रूप में माना जाएगा। तो उन संस्करणों के साथ, अब आप लिख सकते हैं:
perl -e 'while(<<>>){ ...;}' -- *
(यह मत भूलना --
या उपयोग न करें ./*
) इसके डर के बिना फाइलों पर ओवरराइटिंग या अप्रत्याशित कमांड चलाना।
-n
/ फिर -p
भी खतरनाक <>
रूप का उपयोग करते हैं । और सावधान रहना सहानुभूति अभी भी पीछा किया जा रहा है, ताकि जरूरी नहीं है कि यह अविश्वसनीय निर्देशिकाओं में उपयोग करने के लिए सुरक्षित है।