क्लाउड CI सिस्टम में PVS-Studio स्थैतिक विश्लेषक का उपयोग करने के बारे में यह दूसरा लेख है, और इस बार हम Azure DevOps प्लेटफ़ॉर्म पर विचार करेंगे - Microsoft से क्लाउड CI \ CD समाधान। इस बार एक विश्लेषण परियोजना के रूप में, ShareX पर विचार करें।
हमें तीन घटकों की आवश्यकता होगी। पहला PVS-Studio स्थिर विश्लेषक है। दूसरा Azure DevOps है, जिसके साथ हम विश्लेषक को एकीकृत करेंगे। तीसरा एक प्रोजेक्ट है जिसे हम क्लाउड में काम करते समय पीवीएस-स्टूडियो की क्षमताओं को प्रदर्शित करने के लिए जाँचेंगे। तो चलिए शुरू करते हैं।
पीवीएस-स्टूडियो त्रुटियों और सुरक्षा दोषों की खोज के लिए एक स्थिर कोड विश्लेषक है। C, C ++, C # और Java में कोड विश्लेषण करता है।
Azure DevOps । Azure DevOps प्लेटफॉर्म में Azure Pipeline, Azure Board, Azure Artifacts, और अन्य जैसे सॉफ्टवेयर बनाने की प्रक्रिया को तेज करने और इसकी गुणवत्ता में सुधार करने के लिए उपकरण शामिल हैं।
ShareX एक निःशुल्क एप्लिकेशन है जो आपको स्क्रीन के किसी भी हिस्से को कैप्चर करने और रिकॉर्ड करने की अनुमति देता है। यह परियोजना C # में लिखी गई है और यह दर्शाता है कि स्थैतिक विश्लेषक को कैसे चलाया जाए। प्रोजेक्ट के लिए सोर्स कोड
GitHub पर उपलब्ध है ।
ShareX प्रोजेक्ट के लिए क्लॉक कमांड का आउटपुट:
दूसरे शब्दों में, प्रोजेक्ट छोटा है, लेकिन एक क्लाउड प्लेटफॉर्म के साथ संयोजन में पीवीएस-स्टूडियो के काम को प्रदर्शित करने के लिए काफी पर्याप्त है।
चलो सेट करते हैं
Azure DevOps में आरंभ करने के लिए,
लिंक पर क्लिक करें और "स्टार्ट विथ गिटहब" बटन पर क्लिक करें।
GitHub खाते के डेटा के लिए Microsoft अनुप्रयोग एक्सेस देना।
पंजीकरण पूरा करने के लिए एक Microsoft खाता बनाना होगा।
पंजीकरण के बाद, एक परियोजना बनाएं:
अगला, हमें "पाइपलाइन" - "बिल्ड" अनुभाग पर जाने और एक नया बिल्ड पाइपलाइन बनाने की आवश्यकता है
इस सवाल के लिए कि हमारा कोड कहाँ स्थित है, हम जवाब देंगे - GitHub।
हम Azure पाइपलाइन आवेदन को अधिकृत करते हैं और उस परियोजना के साथ भंडार का चयन करते हैं जिसके लिए हम स्थैतिक विश्लेषक के लॉन्च को कॉन्फ़िगर करेंगे
टेम्पलेट चयन विंडो में, "स्टार्टर पाइपलाइन" चुनें।
हम दो तरह से प्रोजेक्ट कोड के स्थैतिक विश्लेषण को चला सकते हैं: Microsoft द्वारा होस्ट या स्व-होस्ट किए गए एजेंटों का उपयोग करना।
पहले संस्करण में, हम Microsoft द्वारा होस्ट किए गए एजेंटों का उपयोग करेंगे। ऐसे एजेंट साधारण आभासी मशीनें हैं जो तब शुरू होती हैं जब हम अपनी पाइपलाइन शुरू करते हैं और कार्य समाप्त होने के बाद हटा दिए जाते हैं। ऐसे एजेंटों का उपयोग आपको समय का समर्थन करने और उन्हें अपडेट करने में समय बर्बाद करने की अनुमति नहीं देता है, लेकिन कुछ प्रतिबंध लगाता है, उदाहरण के लिए, अतिरिक्त सॉफ़्टवेयर स्थापित करने की असंभवता जो परियोजना के निर्माण के लिए उपयोग की जाती है।
Microsoft द्वारा होस्ट किए गए एजेंटों का उपयोग करने के लिए हमारे डिफ़ॉल्ट कॉन्फ़िगरेशन को निम्न से बदलें:
# # master- trigger: - master # # , Docker-, # Windows Server 1803 pool: vmImage: 'win1803' container: microsoft/dotnet-framework:4.7.2-sdk-windowsservercore-1803 steps: # - task: PowerShell@2 inputs: targetType: 'inline' script: 'Invoke-WebRequest -Uri https://files.viva64.com/PVS-Studio_setup.exe -OutFile PVS-Studio_setup.exe' - task: CmdLine@2 inputs: workingDirectory: $(System.DefaultWorkingDirectory) script: | # nuget restore .\ShareX.sln # , md .\PVSTestResults # PVS-Studio_setup.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /COMPONENTS=Core # "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" credentials -u $(PVS_USERNAME) -n $(PVS_KEY) # html. "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" -t .\ShareX.sln -o .\PVSTestResults\ShareX.plog "C:\Program Files (x86)\PVS-Studio\PlogConverter.exe" -t html -o .\PVSTestResults\ .\PVSTestResults\ShareX.plog # - task: PublishBuildArtifacts@1 inputs: pathToPublish: PVSTestResults artifactName: PVSTestResults
नोट: प्रलेखन के अनुसार, उपयोग किए जाने वाले कंटेनर को वर्चुअल मशीन की छवि में कैश किया जाना चाहिए, लेकिन इस लेख को लिखने के समय काम नहीं करता है और कंटेनर को हर बार कार्य शुरू होने पर डाउनलोड किया जाता है, जो निष्पादन के समय को नकारात्मक रूप से प्रभावित करता है।
पाइपलाइन को सहेजें और वैरिएबल बनाएं जिसका उपयोग लाइसेंस फ़ाइल बनाने के लिए किया जाएगा। ऐसा करने के लिए, पाइपलाइन संपादन विंडो खोलें और ऊपरी दाएं कोने में "चर" बटन पर क्लिक करें।
क्रमश: उपयोगकर्ता नाम और लाइसेंस कुंजी वाले दो चर -
PVS_USERNAME और
PVS_KEY जोड़ें।
PVS_KEY वैरिएबल बनाते समय, 2048-बिट RSA कुंजी के साथ चर मान को एन्क्रिप्ट करने के लिए "इस मान को गुप्त रखें" आइटम की जांच
करना न भूलें, साथ ही कार्य निष्पादन लॉग के लिए चर मान के आउटपुट को दबाएं।
हम चर को बचाते हैं और "रन" बटन के साथ पाइपलाइन शुरू करते हैं।
विश्लेषण को चलाने के लिए दूसरा विकल्प एक स्व-होस्टेड एजेंट का उपयोग करना है। स्व-होस्ट किए गए एजेंट ऐसे एजेंट हैं जिन्हें हम स्वयं कॉन्फ़िगर और प्रबंधित करते हैं। ऐसे एजेंट सॉफ़्टवेयर स्थापित करने के लिए अधिक अवसर प्रदान करते हैं, जो हमारे सॉफ़्टवेयर उत्पाद के संयोजन और परीक्षण के लिए आवश्यक है।
ऐसे एजेंटों का उपयोग करने से पहले, उन्हें
निर्देशों के अनुसार कॉन्फ़िगर किया जाना चाहिए, और एक स्थिर विश्लेषक स्थापित और
कॉन्फ़िगर किया जाना चाहिए।
स्व-होस्ट किए गए एजेंट पर कार्य शुरू करने के लिए, हम प्रस्तावित डिफ़ॉल्ट कॉन्फ़िगरेशन को निम्न के साथ बदलते हैं:
# # master- trigger: - master # self-hosted 'MyPool' pool: 'MyPool' steps: - task: CmdLine@2 inputs: workingDirectory: $(System.DefaultWorkingDirectory) script: | # nuget restore .\ShareX.sln # , md .\PVSTestResults # html. "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" -t .\ShareX.sln -o .\PVSTestResults\ShareX.plog "C:\Program Files (x86)\PVS-Studio\PlogConverter.exe" -t html -o .\PVSTestResults\ .\PVSTestResults\ShareX.plog # - task: PublishBuildArtifacts@1 inputs: pathToPublish: PVSTestResults artifactName: PVSTestResults
कार्य पूरा करने के बाद, विश्लेषक रिपोर्ट के साथ संग्रह को सारांश टैब पर डाउनलोड किया जा सकता है, या हम
Send Mail एक्सटेंशन का उपयोग कर सकते हैं, जो आपको ई-मेल भेजने को कॉन्फ़िगर करने, या
मार्केटप्लेस पर अधिक सुविधाजनक टूल की खोज करने की अनुमति देता है।
विश्लेषण परिणामों के बारे में
अब आइए चेक किए गए प्रोजेक्ट में कुछ त्रुटियां देखें - ShareX।
निरर्थक जाँचवार्म अप करने के लिए, आइए कोड में साधारण खामियों से शुरू करते हैं, अर्थात् निरर्थक जाँचों के साथ:
private void PbThumbnail_MouseMove(object sender, MouseEventArgs e) { .... IDataObject dataObject = new DataObject(DataFormats.FileDrop, new string[] { Task.Info.FilePath }); if (dataObject != null) { Program.MainForm.AllowDrop = false; dragBoxFromMouseDown = Rectangle.Empty; pbThumbnail.DoDragDrop(dataObject, DragDropEffects.Copy | DragDropEffects.Move); Program.MainForm.AllowDrop = true; } .... }
PVS-Studio चेतावनी :
V3022 [CWE-571] अभिव्यक्ति 'dataObject! = Null' हमेशा सच होता है। टास्कथंबनेलपेल .cs 415
शून्य के लिए चर
डेटा की जाँच करें पर ध्यान दें। वह यहाँ किस लिए है?
dataObject बस इस मामले में
शून्य नहीं हो सकता है, क्योंकि यह निर्मित ऑब्जेक्ट के संदर्भ के साथ आरंभिक है। परिणामस्वरूप, हमारे पास निरर्थक सत्यापन है। क्या यह महत्वपूर्ण है? नहीं। संक्षिप्त लगता है? नहीं। इस चेक को स्पष्ट रूप से हटा दिया गया है ताकि कोड को अव्यवस्थित न किया जाए।
आइए एक और कोड कोड देखें, जिस पर आप इसी तरह की टिप्पणी कर सकते हैं:
private static Image GetDIBImage(MemoryStream ms) { .... try { .... return new Bitmap(bmp); .... } finally { if (gcHandle != IntPtr.Zero) { GCHandle.FromIntPtr(gcHandle).Free(); } } .... } private static Image GetImageAlternative() { .... using (MemoryStream ms = dataObject.GetData(format) as MemoryStream) { if (ms != null) { try { Image img = GetDIBImage(ms); if (img != null) { return img; } } catch (Exception e) { DebugHelper.WriteException(e); } } } .... }
PVS-Studio चेतावनी :
V3022 [CWE-571] अभिव्यक्ति 'img! = Null' हमेशा सच होती है। क्लिपबोर्ड हेल्पर्स। 289
GetImageAlternative पद्धति फिर से जाँचती है कि
बिटमैप श्रेणी का नया उदाहरण बनाने के तुरंत बाद
img चर
शून्य नहीं है। यहाँ पिछले उदाहरण से अंतर यह है कि
img वैरिएबल को इनिशियलाइज़ करने के लिए, हम कंस्ट्रक्टर का उपयोग नहीं करते हैं, लेकिन
GetDIBImage विधि का। कोड का लेखक मानता है कि इस पद्धति में एक अपवाद हो सकता है, लेकिन केवल
कोशिश करते हैं और
अंत में ब्लॉक को छोड़ देते हैं। इसलिए, यदि कोई अपवाद होता है, तो कॉलिंग विधि
- GetImageAlternative - को
बिटमैप के ऑब्जेक्ट का संदर्भ नहीं मिलेगा
, लेकिन अपने स्वयं के
कैच ब्लॉक में अपवाद को संभालने के लिए मजबूर किया जाएगा। इस स्थिति में,
img वेरिएबल को इनिशियलाइज़ नहीं किया जाएगा, और निष्पादन का धागा चेक
img! = Null तक भी नहीं पहुंचेगा, लेकिन तुरंत
कैच ब्लॉक में आ जाएगा। इसलिए, विश्लेषक ने निरर्थक सत्यापन को इंगित किया।
कोड
V3022 के साथ निम्नलिखित चेतावनी उदाहरण पर विचार करें:
private void btnCopyLink_Click(object sender, EventArgs e) { .... if (lvClipboardFormats.SelectedItems.Count == 0) { url = lvClipboardFormats.Items[0].SubItems[1].Text; } else if (lvClipboardFormats.SelectedItems.Count > 0) { url = lvClipboardFormats.SelectedItems[0].SubItems[1].Text; } .... }
PVS-Studio चेतावनी :
V3022 [CWE-571] अभिव्यक्ति 'lvClipboardFormats.SelectedItems.Count> 0' हमेशा सच होता है। AfterUploadForm.cs 155
आइए दूसरी सशर्त अभिव्यक्ति को देखें। वहां हम रीड-ओनली
काउंट प्रॉपर्टी के मूल्य की जांच करते हैं। यह गुण
चयनितItems संग्रह के एक उदाहरण में तत्वों की संख्या दर्शाता है। शर्त केवल तभी संतुष्ट है जब
गणना गुण शून्य से अधिक हो। सबकुछ ठीक हो जाएगा, लेकिन यह केवल बाहरी में है
अगर बयान कि
गणना पहले से ही जाँच की गई है। सेलेक्ट इट्स संग्रह के एक उदाहरण में शून्य से कम तत्वों की संख्या नहीं हो सकती है, इसलिए,
गणना शून्य के बराबर या शून्य से अधिक मूल्य लेती है। चूँकि हमने पहले से ही चेक का प्रदर्शन किया है
यदि स्टेटमेंट शून्य है, और यह गलत निकला, तो दूसरी ब्रांच पर दूसरा चेक लिखने का कोई मतलब नहीं है कि
काउंट शून्य से अधिक है।
त्रुटि संख्या
V3022 का अंतिम उदाहरण निम्नलिखित कोड टुकड़ा है:
private void DrawCursorGraphics(Graphics g) { .... int cursorOffsetX = 10, cursorOffsetY = 10, itemGap = 10, itemCount = 0; Size totalSize = Size.Empty; int magnifierPosition = 0; Bitmap magnifier = null; if (Options.ShowMagnifier) { if (itemCount > 0) totalSize.Height += itemGap; .... } .... }
PVS-Studio चेतावनी :
V3022 अभिव्यक्ति 'आइटमकाउंट> 0' हमेशा गलत होता है। रीजन्सकैप्ट्योरफॉर्म .cs 1100।
विश्लेषक ने देखा कि स्थिति
आइटम> 0 हमेशा झूठी होगी, क्योंकि थोड़ी अधिक घोषणा की जाती है और एक ही समय में
आइटम संस्करण को शून्य पर
सेट किया जाता है। बहुत ही शर्त पर, इस चर का कहीं भी उपयोग नहीं किया जाता है और इसमें बदलाव नहीं होता है, इसलिए, विश्लेषक ने सशर्त अभिव्यक्ति के बारे में सही निष्कर्ष दिया, जिसका मूल्य हमेशा गलत है।
खैर, अब देखते हैं कि वास्तव में कुछ दिलचस्प है।
बग को समझने का सबसे अच्छा तरीका बग की कल्पना करना है।ऐसा लगता है कि इस जगह पर एक दिलचस्प त्रुटि पाई गई थी:
public static void Pixelate(Bitmap bmp, int pixelSize) { .... float r = 0, g = 0, b = 0, a = 0; float weightedCount = 0; for (int y2 = y; y2 < yLimit; y2++) { for (int x2 = x; x2 < xLimit; x2++) { ColorBgra color = unsafeBitmap.GetPixel(x2, y2); float pixelWeight = color.Alpha / 255; r += color.Red * pixelWeight; g += color.Green * pixelWeight; b += color.Blue * pixelWeight; a += color.Alpha * pixelWeight; weightedCount += pixelWeight; } } .... ColorBgra averageColor = new ColorBgra((byte)(b / weightedCount), (byte)(g / weightedCount), (byte)(r / weightedCount), (byte)(a / pixelCount)); .... }
मैं तुरंत सभी कार्डों को प्रकट नहीं करना चाहता हूं और यह दिखाता हूं कि हमारे विश्लेषक ने यहां क्या पाया है, इसलिए इस क्षण को थोड़ी देर के लिए स्थगित कर दें।
विधि के नाम से, यह अनुमान लगाना आसान है कि यह क्या करता है - आप एक छवि या छवि के एक टुकड़े को एक इनपुट के रूप में प्रस्तुत करते हैं, और यह इसकी पिक्सेलेशन करता है। विधि कोड काफी लंबा है, इसलिए हमने इसे यहां इसकी संपूर्णता में नहीं दिया है, लेकिन बस इसके एल्गोरिथ्म को समझाने और समझाने की कोशिश करते हैं कि यहां किस तरह का बग पीवीएस-स्टूडियो पाया गया।
यह विधि दो मापदंडों को एक इनपुट के रूप में स्वीकार करती है: प्रकार
बिटमैप की एक वस्तु और प्रकार
इंट का मान, जो पिक्सेल के आकार को इंगित करता है। ऑपरेशन एल्गोरिथ्म काफी सरल है:
1) हम इनपुट पर प्राप्त छवि के टुकड़े को पिक्सेल के आकार के बराबर एक पक्ष के साथ वर्गों में तोड़ते हैं। उदाहरण के लिए, यदि हमारे पास 15 का पिक्सेल आकार है, तो हमें एक वर्ग मिलता है जिसमें 15x15 = 225 पिक्सेल होते हैं।
2) अगला, हम इस वर्ग में प्रत्येक पिक्सेल के चारों ओर जाते हैं और
रेड ,
ग्रीन ,
ब्लू और
अल्फा फ़ील्ड के मानों को मध्यवर्ती चर में संचित करते हैं, और पहले इसी रंग मूल्य और
पिक्सेल चैनल द्वारा अल्फा चैनल मान को
गुणा करते हैं , जो
अल्फा मान को 255 से विभाजित करके प्राप्त होता है (
अल्फा चर है) टाइप
बाइट )। साथ ही, जब पिक्सेल को ट्रैवर्स किया जाता है, तो हम
भारितकाउंट नामक एक चर में
पिक्सेलवेइट में दर्ज मानों को
जोड़ते हैं ।
उपरोक्त चरणों को करने वाला कोड स्निपेट निम्नानुसार है:
ColorBgra color = unsafeBitmap.GetPixel(x2, y2); float pixelWeight = color.Alpha / 255; r += color.Red * pixelWeight; g += color.Green * pixelWeight; b += color.Blue * pixelWeight; a += color.Alpha * pixelWeight; weightedCount += pixelWeight;
वैसे, ध्यान दें कि यदि
अल्फा चर का मान शून्य है, तो
पिक्सेलवेट इस पिक्सेल के लिए चर
भारितकाउंट में कोई मूल्य नहीं जोड़ेगा। हमें भविष्य में इसकी आवश्यकता होगी।
3) वर्तमान वर्ग में सभी पिक्सल को बायपास करने के बाद, हम इस वर्ग के लिए सामान्य "औसत" रंग बना सकते हैं। इन क्रियाओं को करने वाला कोड इस प्रकार है:
ColorBgra averageColor = new ColorBgra((byte)(b / weightedCount), (byte)(g / weightedCount), (byte)(r / weightedCount), (byte)(a / pixelCount));
4) अब जब हमारे पास अंतिम रंग है और इसे चर
औसतनकोल पर लिखना है , तो हम फिर से वर्ग में प्रत्येक पिक्सेल के चारों ओर जा सकते हैं और इसे
औसत रंग से मान
दे सकते हैं ।
5) जब तक कच्चे चौराहे हैं तब तक हम चरण 2 पर लौटते हैं।
एक बार फिर, हम ध्यान दें कि चर
भारितकाउंट सभी पिक्सल वर्ग की संख्या के बराबर नहीं है। उदाहरण के लिए, यदि छवि में एक बिल्कुल पारदर्शी पिक्सेल होता है (अल्फा चैनल पर मान शून्य है), तो इस पिक्सेल (
0/255 = 0) के लिए पिक्सेल
वाइट शून्य होगा, इसलिए, यह पिक्सेल
भारितकाउंट चर के मूल्य के निर्माण में कोई योगदान नहीं करेगा। यह तार्किक है - यह बिल्कुल पारदर्शी पिक्सेल के रंगों को ध्यान में रखने का कोई मतलब नहीं है।
सब कुछ काफी उचित लगता है - पिक्सेलेशन को सही ढंग से काम करना चाहिए। और यह वास्तव में सही काम करता है। यह सिर्फ उन png छवियों के लिए नहीं है, जिनमें 255 से कम अल्फा चैनल में मान हैं और शून्य से असमान हैं। नीचे पिक्सेल छवि पर ध्यान दें:
क्या आपने पिक्सेलेशन देखा? और हम नहीं हैं। खैर, अब इस छोटे साज़िश का खुलासा करते हैं और बताते हैं कि इस विधि में बग कहाँ छिपा है।
पिक्सेल वाइट वैरिएबल के मान की गणना करने के लिए लाइन में त्रुटि सामने
आई :
float pixelWeight = color.Alpha / 255;
तथ्य यह है कि कोड के लेखक, चर
पिक्सेलवेइट को एक प्रकार की
फ्लोट के रूप में घोषित करते हुए, निहित करते हैं कि जब
अल्फा फ़ील्ड को 255 से विभाजित किया जाए, तो शून्य और एक के अलावा, भिन्नात्मक संख्या प्राप्त की जानी चाहिए। यह वह जगह है जहां समस्या निहित है, चूंकि
अल्फा चर
बाइट का प्रकार है, और जब इसे 255 से विभाजित किया जाता है, तो हमें पूर्णांक मान मिलता है, और उसके बाद ही यह अस्थायी रूप से
फ्लोट करने के लिए डाली जाएगी, इसलिए, भिन्नात्मक भाग खो जाता है।
पीएनजी छवियों को चित्रित करने में असमर्थता, जिसमें कुछ हद तक पारदर्शिता है, यह स्पष्ट करना आसान है। चूँकि इन पिक्सेल के लिए अल्फा चैनल मान 0 रेंज में
निहित है । <अल्फा <255, जब
अल्फा वैरिएबल को 255 से विभाजित किया जाता है, तो हमें हमेशा 0. मिलेगा। इसलिए,
पिक्सेल वाइट ,
आर ,
जी ,
बी ,
ए ,
भारितकाउंट चर के मान भी हमेशा होते हैं। शून्य होगा। नतीजतन, हमारा औसत रंग औसत रंग सभी चैनलों पर शून्य मान के साथ होगा: लाल - 0, नीला - 0, हरा - 0, अल्फा - 0. इस रंग के साथ वर्ग को भरना, हम पिक्सेल के मूल रंग को नहीं बदलते हैं, क्योंकि
औसत रंग बिल्कुल पारदर्शी है। । इस त्रुटि को ठीक करने के लिए, आपको बस स्पष्ट रूप से
फ़्लोट प्रकार के लिए
अल्फा फ़ील्ड डालना होगा। कोड की सही लाइन इस तरह दिख सकती है:
float pixelWeight = (float)color.Alpha / 255;
और यह उस संदेश का हवाला देने का समय है जो पीवीएस-स्टूडियो ने गलत कोड को दिया है:
PVS-Studio चेतावनी :
V3041 [CWE-682] अभिव्यक्ति को 'int' प्रकार से 'फ्लोट' प्रकार में डाला गया था। एक आंशिक भाग के नुकसान से बचने के लिए एक स्पष्ट प्रकार के कलाकारों का उपयोग करने पर विचार करें। एक उदाहरण: डबल ए = (डबल) (एक्स) / वाई ;; ImageHelpers.cs 1119।
और तुलना के लिए, हम एप्लिकेशन के एक निश्चित संस्करण पर प्राप्त की गई वास्तव में पिक्सेलयुक्त छवि का स्क्रीनशॉट देते हैं:
संभावित NullReferenceException public static bool AddMetadata(Image img, int id, string text) { .... pi.Value = bytesText; if (pi != null) { img.SetPropertyItem(pi); return true; } .... }
PVS-Studio चेतावनी: V3095 [CWE-476] 'pi' ऑब्जेक्ट का उपयोग इससे पहले किया गया था जब इसे null के खिलाफ सत्यापित किया गया था। जाँच लाइनें: 801, 803. ImageHelpers.cs 801
इस कोड के टुकड़े से पता चलता है कि इसके लेखक को उम्मीद थी कि
pi वेरिएबल
अशक्त होगा , यही वजह है कि
SetPropertyItem पद्धति को कॉल करने से पहले
pi! = Null चेक किया जाता है। यह अजीब है कि इस जाँच से पहले, एक बाइट सरणी को
pi.Value संपत्ति को सौंपा गया है, क्योंकि यदि
p null है , तो
NullReferenceException प्रकार का अपवाद फेंक दिया जाएगा।
इसी तरह की स्थिति कहीं और देखी गई:
private static void Task_TaskCompleted(WorkerTask task) { .... task.KeepImage = false; if (task != null) { if (task.RequestSettingUpdate) { Program.MainForm.UpdateCheckStates(); } .... } .... }
PVS-Studio चेतावनी: V3095 [CWE-476] नल के खिलाफ सत्यापित होने से पहले 'कार्य' ऑब्जेक्ट का उपयोग किया गया था। चेक लाइनें: 268, 270. टास्कमैनएगर ।cs 268
PVS-Studio को एक और समान त्रुटि मिली। अर्थ अभी भी समान है, इसलिए कोड टुकड़ा देने की कोई बहुत आवश्यकता नहीं है, हम खुद को विश्लेषक संदेश तक सीमित रखते हैं।
PVS-Studio चेतावनी: V3095 [CWE-476] नल के खिलाफ सत्यापित होने से पहले 'Config.PhotobucketAccountInfo' ऑब्जेक्ट का उपयोग किया गया था। चेक लाइनें: 216, 219. अपलोडर्सकॉन्फिगफॉर्म .cs 216
वही वापसी मूल्यWindowsList वर्ग की
EvalWindows विधि में एक संदिग्ध टुकड़ा खोजा गया था, जो किसी भी परिस्थिति में
सही है:
public class WindowsList { public List<IntPtr> IgnoreWindows { get; set; } .... public WindowsList() { IgnoreWindows = new List<IntPtr>(); } public WindowsList(IntPtr ignoreWindow) : this() { IgnoreWindows.Add(ignoreWindow); } .... private bool EvalWindows(IntPtr hWnd, IntPtr lParam) { if (IgnoreWindows.Any(window => hWnd == window)) { return true;
PVS-Studio चेतावनी: V3009 यह विचित्र है कि यह विधि हमेशा एक और 'समान' का सही मान देती है। WindowsList.cs 82
यह तर्कसंगत लगता है कि यदि
hWnd के समान मूल्य वाले एक सूचक को
IgnoreWindows नाम के साथ सूची में पाया गया, तो विधि को
गलत वापस लौटना चाहिए।
IgnoreWindows सूची को या तो
WindowsList कंस्ट्रक्टर
(IntPtr अनदेखा) , या सीधे संपत्ति तक पहुंच के माध्यम से, यह सार्वजनिक होने के बाद से आबाद किया जा सकता है। विज़ुअल स्टूडियो के अनुसार, एक तरीका या दूसरा, कोड में फिलहाल यह सूची किसी भी तरह से भरी नहीं गई है। यह इस पद्धति का एक और विचित्र स्थान है।
ईवेंट हैंडलर्स को असुरक्षित कॉल protected void OnNewsLoaded() { if (NewsLoaded != null) { NewsLoaded(this, EventArgs.Empty); } }
PVS-Studio चेतावनी: V3083 [CWE-367] इवेंट 'NewsLoaded' का असुरक्षित आमंत्रण, NullReferenceException संभव है। इसे लागू करने से पहले एक स्थानीय चर को घटना असाइन करने पर विचार करें। NewsListControl.cs 111
इस स्थिति में, निम्न अप्रिय स्थिति उत्पन्न हो सकती है:
अशक्त असमानता के लिए
NewsLoaded चर की जाँच करने के बाद, जिस प्रक्रिया से घटना की प्रक्रिया होती है, वह सदस्यता समाप्त हो सकती है, उदाहरण के लिए, किसी अन्य थ्रेड में, और जब हम
स्टेटमेंट के शरीर में आते हैं
यदि कथन ,
NewsLoaded परिवर्तनशील पहले
से ही होगा बराबर होता है। एक
न्यूज़लैबड इवेंट पर ग्राहकों को कॉल करने का प्रयास करना जो
अशक्त है , एक
NullReferenceException को फेंक देगा। यह अशक्त सशर्त ऑपरेटर का उपयोग करने के लिए अधिक सुरक्षित है और ऊपर दिए गए कोड को निम्नानुसार फिर से लिखना चाहिए:
protected void OnNewsLoaded() { NewsLoaded?.Invoke(this, EventArgs.Empty); }
विश्लेषक ने
68 और समान स्थानों का संकेत दिया। हम यहां उनका वर्णन नहीं करेंगे - उनमें इवेंट कॉल का पैटर्न समान है।
ToString से अशक्त लौटेंबहुत पहले नहीं, एक सहकर्मी के
दिलचस्प लेख से, मुझे पता चला कि Microsoft ओवरराइड
टोस्ट विधि से
अशक्त लौटने की सलाह नहीं देता है। पीवीएस-स्टूडियो इससे अच्छी तरह वाकिफ है:
public override string ToString() { lock (loggerLock) { if (sbMessages != null && sbMessages.Length > 0) { return sbMessages.ToString(); } return null; } }
PVS-Studio चेतावनी: V3108 यह 'ToSting ()' विधि से 'null' वापस करने के लिए अनुशंसित नहीं है। लकड़हारा। 167
उपयोग न करने पर उचित क्यों? public SeafileCheckAccInfoResponse GetAccountInfo() { string url = URLHelpers.FixPrefix(APIURL); url = URLHelpers.CombineURL(APIURL, "account/info/?format=json"); .... }
PVS-Studio चेतावनी: V3008 'url' चर को क्रमिक रूप से दो बार मान दिया गया है। शायद यह एक गलती है। चेक लाइनें: 197, 196. सीफाइल। 197
जैसा कि आप उदाहरण से देख सकते हैं, जब
url वैरिएबल की घोषणा करते हुए, इसे
FixPrefix विधि से लौटाए गए कुछ मान को असाइन किया गया है। अगली पंक्ति में, हम परिणामी मूल्य को "पीस" देते हैं, यहां तक कि कहीं भी इसका उपयोग किए बिना। हमें "मृत कोड" के समान कुछ मिलता है - यह काम करता है, यह अंतिम परिणाम को प्रभावित नहीं करता है। यह त्रुटि कॉपी-पेस्ट के परिणाम की संभावना है, क्योंकि इस तरह के कोड टुकड़े 9 और तरीकों में पाए जाते हैं।
एक उदाहरण के लिए, हम एक समान पहली पंक्ति के साथ दो तरीके देते हैं:
public bool CheckAuthToken() { string url = URLHelpers.FixPrefix(APIURL); url = URLHelpers.CombineURL(APIURL, "auth/ping/?format=json"); .... } .... public bool CheckAPIURL() { string url = URLHelpers.FixPrefix(APIURL); url = URLHelpers.CombineURL(APIURL, "ping/?format=json"); .... }
कुल मिलाकर
जैसा कि हम देख सकते हैं, विश्लेषक द्वारा स्वत: सत्यापन स्थापित करने की जटिलता केवल चयनित सीआई प्रणाली पर निर्भर नहीं है - केवल 15 मिनट और माउस के कुछ क्लिकों में, हम एक स्थैतिक विश्लेषक के साथ हमारे प्रोजेक्ट कोड का सत्यापन सेट करते हैं।
निष्कर्ष में, हम सुझाव देते हैं कि आप अपनी परियोजनाओं पर
विश्लेषक को
डाउनलोड करें और प्रयास करें ।

यदि आप इस लेख को अंग्रेजी बोलने वाले दर्शकों के साथ साझा करना चाहते हैं, तो कृपया अनुवाद के लिंक का उपयोग करें: ओलेग एंड्रीव, इल्या नैनीलिन।
पीवीएस-स्टूडियो इन द क्लाउड्स: एज़्योर देवओपीएस ।