2013-03-04 4 views
86

मुझे कुछ कोड के साथ एक स्थिति है जहां eval() एक संभावित समाधान के रूप में आया था। अब eval() का उपयोग करने के लिए मेरे पास कभी भी नहीं था, लेकिन संभावित खतरे के कारण मुझे बहुत सारी जानकारी मिली है। उस ने कहा, मैं इसका उपयोग करने के बारे में बहुत सावधान हूँ।पायथन के eval() बनाम ast.literal_eval() बनाम?

कहाँ datamap जरूरतों एक शब्दकोश होने के लिए:

मेरे स्थिति मैं इनपुट एक उपयोगकर्ता द्वारा दिया जा रहा है है। मैंने चारों ओर खोज की और पाया कि eval() इसे काम कर सकता है। मैंने सोचा कि मैं डेटा का उपयोग करने से पहले इनपुट के प्रकार की जांच करने में सक्षम हो सकता हूं और एक व्यवहार्य सुरक्षा सावधानी बरतनी होगी।

datamap = eval(raw_input('Provide some data here: ') 
if not isinstance(datamap, dict): 
    return 

मैंने दस्तावेज़ों के माध्यम से पढ़ा और मैं अभी भी अस्पष्ट हूं कि यह सुरक्षित होगा या नहीं। क्या उत्तीर्ण डेटा के मूल्यांकन के तुरंत बाद या datamap परिवर्तनीय के बाद मूल्यांकन किया जाता है?

ast मॉड्यूल .literal_eval() एकमात्र सुरक्षित विकल्प है?

उत्तर

110

datamap = eval(raw_input('Provide some data here: ')) मतलब यह है कि आप वास्तव में इससे पहले कि आप असुरक्षित होने का समझे या कोड का मूल्यांकन नहीं। जैसे ही फ़ंक्शन कहा जाता है, यह कोड का मूल्यांकन करता है। the dangers of eval भी देखें।

ast.literal_eval एक अपवाद उठाता है यदि इनपुट वैध पायथन डेटाटाइप नहीं है, तो कोड निष्पादित नहीं किया जाएगा यदि यह नहीं है।

ast.literal_eval का उपयोग करें जब भी आपको eval की आवश्यकता हो। आपको आमतौर पर शाब्दिक पायथन कथन का मूल्यांकन नहीं करना चाहिए।

+7

यह 100% सही सलाह नहीं है क्योंकि किसी भी bitwise ऑपरेटरों (या अधिभारित ऑपरेटरों) विफल हो जाएगा। उदाहरण के लिए। 'ast.literal_eval (" 1 और 1 ") 'एक त्रुटि फेंक देगा लेकिन' eval ("1 और 1") 'नहीं होगा। –

+0

बस उत्सुक। अगर हम "1 और 1" जैसी कुछ उम्मीद कर रहे हैं तो क्या हमें अभिव्यक्ति पार्सर्स या कुछ का उपयोग नहीं करना चाहिए? – thelinuxer

+0

@thelinuxer आपको अभी भी चाहिए, हां; आप बस इस तरह के कुछ के लिए 'ast.literal_eval' का उपयोग करने में सक्षम नहीं होंगे (उदा। आप मैन्युअल रूप से एक पार्सर लागू कर सकते हैं)। – Volatility

24

पायथन के मूल्यांकन पर उत्सुक, तो eval(raw_input(...)) जैसे ही यह eval मारता है, क्या आप डेटा बाद में साथ क्या की परवाह किए बिना उपयोगकर्ता के इनपुट का मूल्यांकन करेंगे। इसलिए, यह सुरक्षित नहीं है, खासकर जब आप eval उपयोगकर्ता इनपुट।

ast.literal_eval का उपयोग करें।


उदाहरण के लिए, प्रॉम्प्ट पर इस में प्रवेश करने के लिए बहुत, बहुत बुरा होगा:

__import__('os').system('rm -rf /a-path-you-really-care-about') 
65

ast.literal_eval() केवल समझता है पायथन के वाक्य रचना के एक छोटे सबसेट मान्य होने के लिए:

स्ट्रिंग या केवल निम्नलिखित पायथन शाब्दिक संरचनाओं शामिल हो सकते हैं प्रदान की नोड: स्ट्रिंग, संख्याओं, tuples, सूचियों, dicts, बूलियन्स, और कोई नहीं।

ast.literal_eval() में __import__('os').system('rm -rf /a-path-you-really-care-about') पासिंग एक त्रुटि बढ़ा देंगे, लेकिन eval() खुशी से अपने ड्राइव मिटा देगा।

चूंकि ऐसा लगता है कि आप केवल उपयोगकर्ता इनपुट को एक सादा शब्दकोश देने दे रहे हैं, ast.literal_eval() का उपयोग करें। यह सुरक्षित रूप से करता है जो आप चाहते हैं और कुछ भी नहीं।

21

eval: यह बहुत शक्तिशाली है, लेकिन अगर आप अविश्वसनीय इनपुट से मूल्यांकन करने के लिए स्ट्रिंग स्वीकार करते हैं तो यह भी बहुत खतरनाक है। मान लीजिए कि स्ट्रिंग का मूल्यांकन किया जा रहा है "os.system ('rm -rf /')" है? यह वास्तव में आपके कंप्यूटर पर सभी फाइलों को हटाने शुरू कर देगा।

ast.literal_eval: एक अभिव्यक्ति नोड या पाइथन शाब्दिक या कंटेनर डिस्प्ले युक्त एक स्ट्रिंग का सुरक्षित मूल्यांकन करें। प्रदान की गई स्ट्रिंग या नोड में केवल निम्नलिखित पायथन शाब्दिक संरचनाएं हो सकती हैं: स्ट्रिंग्स, बाइट्स, संख्याएं, टुपल्स, सूचियां, डिब्बे, सेट, बूलियन, कोई नहीं, बाइट्स और सेट।

सिंटेक्स:

eval(expression, globals=None, locals=None) 
ast.literal_eval(node_or_string) 

उदाहरण:

ast.literal_eval("1+1") # output : 2 
ast.literal_eval("{'a': 2, 'b': 3, 3:'xyz'}") # output : {'a': 2, 'b': 3, 3:'xyz'} 
# type dictionary 
ast.literal_eval("",{}) # output : Syntax Error required only one parameter 
ast.literal_eval("__import__('os').system('rm -rf /')") # output : error 

eval("__import__('os').system('rm -rf /')") 
# output : start deleting all the files on your computer. 
# restricting using global and local variables 
eval("__import__('os').system('rm -rf /')",{'__builtins__':{}},{}) 
# output : Error due to blocked imports by passing '__builtins__':{} in global 

# But still eval is not safe. we can access and break the code as given below 
s = """ 
(lambda fc=(
lambda n: [ 
    c for c in 
     ().__class__.__bases__[0].__subclasses__() 
     if c.__name__ == n 
    ][0] 
): 
fc("function")(
    fc("code")(
     0,0,0,0,"KABOOM",(),(),(),"","",0,"" 
    ),{} 
)() 
)() 
""" 
eval(s, {'__builtins__':{}}) 
+0

'ast.literal_eval (" 1 + 1 ") 'मुझे एक त्रुटि दे रहा है। – Mourya

+0

किस पायथन संस्करण में आपको त्रुटि मिल रही है ?? –

+1

मैं अजगर 2.7 का उपयोग कर रहा हूं और मैंने अभी पाइथन 3.x पर अपने कामकाजी जुर्माना की जांच की है। मेरा बुरा मैंने इसे अजगर 2.7 पर कोशिश कर रखा – Mourya

0

तो आपको केवल एक उपयोगकर्ता प्रदान की शब्दकोश है, संभव बेहतर समाधान json.loads है। मुख्य सीमा यह है कि जेसन डिकट्स को स्ट्रिंग कुंजियों की आवश्यकता होती है। इसके अलावा आप केवल शाब्दिक डेटा प्रदान कर सकते हैं, लेकिन यह literal_eval के मामले भी है।

संबंधित मुद्दे