# HG changeset patch # User Alexander Simon # Date 1434652942 25200 # Thu Jun 18 11:42:22 2015 -0700 # Node ID f6d0856cacbc1b83a08ecd55650d10645a978c2b # Parent cc7c8173b70b71c8348cf4f38ec48af723aebab2 fixing Bug #253019 Security checks - add inspection diff --git a/cnd.highlight/src/org/netbeans/modules/cnd/highlight/error/CodeAssistanceHintProvider.java b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/error/CodeAssistanceHintProvider.java --- a/cnd.highlight/src/org/netbeans/modules/cnd/highlight/error/CodeAssistanceHintProvider.java +++ b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/error/CodeAssistanceHintProvider.java @@ -184,7 +184,7 @@ public synchronized Collection getAudits() { if (audits == null) { List res = new ArrayList<>(); - for(CodeAuditFactory factory : Lookups.forPath(CodeAuditFactory.REGISTRATION_PATH+NAME).lookupAll(CodeAuditFactory.class)) { + for(CodeAuditFactory factory : Lookups.forPath(CodeAuditFactory.REGISTRATION_PATH+CodeAssistanceHintProvider.NAME).lookupAll(CodeAuditFactory.class)) { res.add(factory.create(myPreferences)); } Collections.sort(res, new Comparator(){ diff --git a/cnd.highlight/src/org/netbeans/modules/cnd/highlight/hints/CsmHintProvider.java b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/hints/CsmHintProvider.java --- a/cnd.highlight/src/org/netbeans/modules/cnd/highlight/hints/CsmHintProvider.java +++ b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/hints/CsmHintProvider.java @@ -57,6 +57,7 @@ import org.netbeans.modules.cnd.api.model.syntaxerr.CodeAuditFactory; import org.netbeans.modules.cnd.api.model.syntaxerr.CodeAuditProvider; import org.netbeans.modules.cnd.api.model.syntaxerr.CsmErrorProvider; +import org.netbeans.modules.cnd.highlight.security.SecurityCheckProvider; import org.netbeans.modules.cnd.utils.CndUtils; import org.netbeans.modules.cnd.utils.MIMENames; import org.openide.util.Lookup; @@ -185,7 +186,7 @@ public synchronized Collection getAudits() { if (audits == null) { List res = new ArrayList<>(); - for(CodeAuditFactory factory : Lookups.forPath(CodeAuditFactory.REGISTRATION_PATH+NAME).lookupAll(CodeAuditFactory.class)) { + for(CodeAuditFactory factory : Lookups.forPath(CodeAuditFactory.REGISTRATION_PATH+CsmHintProvider.NAME).lookupAll(CodeAuditFactory.class)) { res.add(factory.create(myPreferences)); } Collections.sort(res, new Comparator(){ diff --git a/cnd.highlight/src/org/netbeans/modules/cnd/highlight/hints/HintAnalyzerImpl.java b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/hints/HintAnalyzerImpl.java --- a/cnd.highlight/src/org/netbeans/modules/cnd/highlight/hints/HintAnalyzerImpl.java +++ b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/hints/HintAnalyzerImpl.java @@ -56,6 +56,7 @@ import org.netbeans.modules.cnd.api.model.CsmFile; import org.netbeans.modules.cnd.api.model.syntaxerr.CsmErrorInfo; import org.netbeans.modules.cnd.api.model.syntaxerr.CsmErrorProvider; +import org.netbeans.modules.cnd.highlight.security.SecurityCheckProvider; import org.netbeans.modules.cnd.modelutil.CsmUtilities; import org.netbeans.spi.editor.hints.ErrorDescription; import org.netbeans.spi.editor.hints.ErrorDescriptionFactory; diff --git a/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/Bundle.properties b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/Bundle.properties new file mode 100644 --- /dev/null +++ b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/Bundle.properties @@ -0,0 +1,49 @@ +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2015 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU +# General Public License Version 2 only ("GPL") or the Common +# Development and Distribution License("CDDL") (collectively, the +# "License"). You may not use this file except in compliance with the +# License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the +# specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header +# Notice in each file and include the License file at +# nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that +# accompanied this code. If applicable, add the following below the +# License Header, with the fields enclosed by brackets [] replaced by +# your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# If you wish your version of this file to be governed by only the CDDL +# or only the GPL Version 2, indicate your decision by adding +# "[Contributor] elects to include this software in this distribution +# under the [CDDL or GPL Version 2] license." If you do not indicate a +# single choice of license, a recipient has the option to distribute +# your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. +# However, if you add GPL Version 2 code and therefore, elected the GPL +# Version 2 license, then the option applies only if the new code is +# made subject to such option by the copyright holder. +# +# Contributor(s): +# +# Portions Copyrighted 2015 Sun Microsystems, Inc. + +SecurityCheck_NAME=Security issues +SecurityCheck_DESCRIPTION=Possible security flaws +DisableHint=Configure Hints + +#AvoidFunctionUsage +UsingUnsafeFunctions.Unsafe.name=C library functions: highly unsafe +UsingUnsafeFunctions.Unsafe.description=These function cannot be used securely so it should not to be used under any circumstances +UsingUnsafeFunctions.Avoid.name=C library functions: difficult to use securely +UsingUnsafeFunctions.Avoid.description=Use should be avoided as this function is difficult to use securely \ No newline at end of file diff --git a/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/Checks.java b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/Checks.java new file mode 100644 --- /dev/null +++ b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/Checks.java @@ -0,0 +1,138 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2015 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2015 Sun Microsystems, Inc. + */ +package org.netbeans.modules.cnd.highlight.security; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import org.netbeans.modules.cnd.api.model.CsmFile; +import org.netbeans.modules.cnd.api.model.CsmFunction; +import org.netbeans.modules.cnd.api.model.CsmInclude; +import org.netbeans.modules.cnd.api.model.services.CsmFileInfoQuery; +import org.openide.util.Exceptions; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * + * @author Danila Sergeyev + */ +public class Checks { + private static final String levelTagName = "level"; // NOI18N + private static final String[] levelTagAttributes = {"value"}; // NOI18N + private static final String functionTagName = "function"; // NOI18N + private static final String[] functionTagAttributes = {"name", "header"}; // NOI18N + + public enum Level { + AVOID, + UNSAFE + } + + private final Map unsecureFunctions; + private final String level; + + private Checks(Level level) { + if (level == Level.AVOID) { + this.level = "avoid"; // NOI18N + } else { + this.level = "unsafe"; // NOI18N + } + unsecureFunctions = new HashMap<>(); + processXml(); + } + + private void processXml() { + try { + Document doc = DocumentBuilderFactory.newInstance() + .newDocumentBuilder() + .parse(Checks.class.getResourceAsStream("Checks.xml")); // NOI18N + + NodeList levelNodes = doc.getElementsByTagName(levelTagName); + for (int i = 0, ilimit = levelNodes.getLength(); i < ilimit; i++) { + Node levelNode = levelNodes.item(i); + if (levelNode.getNodeType() == Node.ELEMENT_NODE) { + Element levelElement = (Element) levelNode; + String value = levelElement.getAttribute(levelTagAttributes[0]); + if (value != null && value.equals(level)) { + NodeList nodes = levelNode.getChildNodes(); + for (int j = 0, jlimit = nodes.getLength(); j < jlimit; j++) { + Node node = nodes.item(j); + if (node.getNodeName().equals(functionTagName) && node.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) node; + String name = element.getAttribute(functionTagAttributes[0]); + String header = element.getAttribute(functionTagAttributes[1]); + unsecureFunctions.put(name, header); + } + } + } + } + } + + } catch (ParserConfigurationException | SAXException | IOException ex) { + Exceptions.printStackTrace(ex); + } + } + + public static Checks getInstance(Level level) { + return new Checks(level); + } + + public boolean isUnsecuredFunction(CsmFunction function) { + String fname = function.getName().toString(); + String header = unsecureFunctions.get(fname); + if (header != null) { + CsmFile file = function.getContainingFile(); + for (CsmInclude include : CsmFileInfoQuery.getDefault().getIncludeStack(file)) { + if (include.getIncludeName().toString().equals(header)) { + return true; + } + } + } + return false; + } + +} diff --git a/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/Checks.xml b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/Checks.xml new file mode 100644 --- /dev/null +++ b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/Checks.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + diff --git a/cnd.highlight/src/org/netbeans/modules/cnd/highlight/hints/HintAnalyzerImpl.java b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/SecurityAnalyzerImpl.java copy from cnd.highlight/src/org/netbeans/modules/cnd/highlight/hints/HintAnalyzerImpl.java copy to cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/SecurityAnalyzerImpl.java --- a/cnd.highlight/src/org/netbeans/modules/cnd/highlight/hints/HintAnalyzerImpl.java +++ b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/SecurityAnalyzerImpl.java @@ -40,7 +40,7 @@ * Portions Copyrighted 2014 Sun Microsystems, Inc. */ -package org.netbeans.modules.cnd.highlight.hints; +package org.netbeans.modules.cnd.highlight.security; import java.util.ArrayList; import java.util.Collection; @@ -70,19 +70,19 @@ * * @author Alexander Simon */ -public class HintAnalyzerImpl extends AbstractAnalyzer { +public class SecurityAnalyzerImpl extends AbstractAnalyzer { private static final String PREFIX = "cnd-"; //NOI18N - private HintAnalyzerImpl(Context ctx) { + private SecurityAnalyzerImpl(Context ctx) { super(ctx); } @Override protected CsmErrorProvider getErrorProvider(Preferences preferences) { if (preferences != null) { - return new CsmHintProvider(preferences); + return new SecurityCheckProvider(preferences); } else { - return CsmHintProvider.getInstance(); + return (CsmErrorProvider) SecurityCheckProvider.getInstance(); } } @@ -139,17 +139,17 @@ public static final class AnalyzerFactoryImpl extends AnalyzerFactory { public AnalyzerFactoryImpl() { - super(CsmHintProvider.NAME, - NbBundle.getMessage(CsmHintProvider.class, "General_DESCRIPTION"), //NOI18N + super(SecurityCheckProvider.NAME, + NbBundle.getMessage(SecurityCheckProvider.class, "SecurityCheck_DESCRIPTION"), //NOI18N ImageUtilities.loadImage("org/netbeans/modules/cnd/highlight/resources/bugs.png")); //NOI18N } @Override public Iterable getWarnings() { List result = new ArrayList<>(); - final CsmHintProvider provider = (CsmHintProvider)CsmHintProvider.getInstance(); + final SecurityCheckProvider provider = (SecurityCheckProvider)SecurityCheckProvider.getInstance(); for(CodeAudit audit : provider.getAudits()) { - result.add(WarningDescription.create(PREFIX+audit.getID(), audit.getName(), CsmHintProvider.NAME, provider.getDisplayName())); + result.add(WarningDescription.create(PREFIX+audit.getID(), audit.getName(), SecurityCheckProvider.NAME, provider.getDisplayName())); } return result; } @@ -185,15 +185,15 @@ private CodeAuditProvider getErrorProvider(Preferences preferences) { if (preferences != null) { - return new CsmHintProvider(preferences); + return new SecurityCheckProvider(preferences); } else { - return (CodeAuditProvider)CsmHintProvider.getInstance(); + return (CodeAuditProvider)SecurityCheckProvider.getInstance(); } } @Override public Analyzer createAnalyzer(Context context) { - return new HintAnalyzerImpl(context); + return new SecurityAnalyzerImpl(context); } } } diff --git a/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/SecurityCheckProvider.java b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/SecurityCheckProvider.java new file mode 100644 --- /dev/null +++ b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/SecurityCheckProvider.java @@ -0,0 +1,185 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2015 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2015 Sun Microsystems, Inc. + */ +package org.netbeans.modules.cnd.highlight.security; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.prefs.BackingStoreException; +import java.util.prefs.Preferences; +import org.netbeans.modules.cnd.api.model.CsmFile; +import org.netbeans.modules.cnd.api.model.services.CsmCacheManager; +import org.netbeans.modules.cnd.api.model.syntaxerr.AbstractCodeAudit; +import org.netbeans.modules.cnd.api.model.syntaxerr.AuditPreferences; +import org.netbeans.modules.cnd.api.model.syntaxerr.CodeAudit; +import org.netbeans.modules.cnd.api.model.syntaxerr.CodeAuditFactory; +import org.netbeans.modules.cnd.api.model.syntaxerr.CodeAuditProvider; +import org.netbeans.modules.cnd.api.model.syntaxerr.CsmErrorProvider; +import org.netbeans.modules.cnd.utils.MIMENames; +import org.openide.util.Lookup; +import org.openide.util.NbBundle; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ServiceProvider; +import org.openide.util.lookup.ServiceProviders; + +/** + * + * @author Danila Sergeyev + */ +@ServiceProviders({ + @ServiceProvider(service = CsmErrorProvider.class, position = 1200), + @ServiceProvider(service = CodeAuditProvider.class, position = 1300) +}) +public class SecurityCheckProvider extends CsmErrorProvider implements CodeAuditProvider { + public static final String NAME = "SecurityCheck"; //NOI18N + private Collection audits; + private final AuditPreferences myPreferences; + + public static CodeAuditProvider getInstance() { + for(CodeAuditProvider provider : Lookup.getDefault().lookupAll(CodeAuditProvider.class)) { + if (NAME.equals(provider.getName())) { + return provider; + } + } + return null; + } + + public SecurityCheckProvider() { + myPreferences = new AuditPreferences(AuditPreferences.AUDIT_PREFERENCES_ROOT.node(NAME)); + } + + SecurityCheckProvider(Preferences preferences) { + try { + if (preferences.nodeExists(NAME)) { + preferences = preferences.node(NAME); + } + } catch (BackingStoreException ex) { + } + if (preferences.absolutePath().endsWith("/"+NAME)) { //NOI18N + myPreferences = new AuditPreferences(preferences); + } else { + myPreferences = new AuditPreferences(preferences.node(NAME)); + } + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getDisplayName() { + return NbBundle.getMessage(SecurityCheckProvider.class, "SecurityCheck_NAME"); //NOI18N + } + + @Override + public String getDescription() { + return NbBundle.getMessage(SecurityCheckProvider.class, "SecurityCheck_DESCRIPTION"); //NOI18N + } + + @Override + protected void doGetErrors(CsmErrorProvider.Request request, CsmErrorProvider.Response response) { + CsmFile file = request.getFile(); + if (file != null) { + if (request.isCancelled()) { + return; + } + CsmCacheManager.enter(); + try { + for(CodeAudit audit : getAudits()) { + if (request.isCancelled()) { + return; + } + AbstractCodeAudit engine = (AbstractCodeAudit)audit; + if (engine.isEnabled() && engine.isSupportedEvent(request.getEvent())) { + engine.doGetErrors(request, response); + } + } + } finally { + CsmCacheManager.leave(); + } + } + } + + @Override + public synchronized Collection getAudits() { + if (audits == null) { + List res = new ArrayList<>(); + for(CodeAuditFactory factory : Lookups.forPath(CodeAuditFactory.REGISTRATION_PATH+SecurityCheckProvider.NAME).lookupAll(CodeAuditFactory.class)) { + res.add(factory.create(myPreferences)); + } + Collections.sort(res, new Comparator(){ + + @Override + public int compare(CodeAudit o1, CodeAudit o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + audits = res; + } + return audits; + } + + @Override + public AuditPreferences getPreferences() { + return myPreferences; + } + + @Override + public String getMimeType() { + return MIMENames.SOURCES_MIME_TYPE; + } + + @Override + public boolean isSupportedEvent(CsmErrorProvider.EditorEvent kind) { + for(CodeAudit audit : getAudits()) { + AbstractCodeAudit engine = (AbstractCodeAudit)audit; + if (engine.isSupportedEvent(kind)) { + return true; + } + } + return false; + } + +} diff --git a/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/UsingUnsafeFunctions.java b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/UsingUnsafeFunctions.java new file mode 100644 --- /dev/null +++ b/cnd.highlight/src/org/netbeans/modules/cnd/highlight/security/UsingUnsafeFunctions.java @@ -0,0 +1,127 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2015 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2015 Sun Microsystems, Inc. + */ +package org.netbeans.modules.cnd.highlight.security; + +import org.netbeans.modules.cnd.analysis.api.AnalyzerResponse; +import org.netbeans.modules.cnd.api.model.CsmFile; +import org.netbeans.modules.cnd.api.model.CsmFunction; +import org.netbeans.modules.cnd.api.model.syntaxerr.AbstractCodeAudit; +import org.netbeans.modules.cnd.api.model.syntaxerr.AuditPreferences; +import org.netbeans.modules.cnd.api.model.syntaxerr.CodeAuditFactory; +import org.netbeans.modules.cnd.api.model.syntaxerr.CsmErrorInfo; +import org.netbeans.modules.cnd.api.model.syntaxerr.CsmErrorProvider; +import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities; +import org.netbeans.modules.cnd.api.model.xref.CsmReference; +import org.netbeans.modules.cnd.api.model.xref.CsmReferenceResolver; +import org.netbeans.modules.cnd.highlight.hints.ErrorInfoImpl; +import org.openide.util.NbBundle; +import org.openide.util.lookup.ServiceProvider; + +/** + * + * @author Danila Sergeyev + */ +public class UsingUnsafeFunctions extends AbstractCodeAudit { + private final Checks.Level level; + private static final String avoidName = "UsingUnsafeFunctions.Avoid.name"; // NOI18N + private static final String avoidDescription = "UsingUnsafeFunctions.Avoid.description"; // NOI18N + private static final String unsafeName = "UsingUnsafeFunctions.Unsafe.name"; // NOI18N + private static final String unsafeDescription = "UsingUnsafeFunctions.Unsafe.description"; // NOI18N + + private UsingUnsafeFunctions(Checks.Level level, String id, String name, String description, String defaultSeverity, boolean defaultEnabled, AuditPreferences myPreferences) { + super(id, name, description, defaultSeverity, defaultEnabled, myPreferences); + this.level = level; + } + + @Override + public boolean isSupportedEvent(CsmErrorProvider.EditorEvent kind) { + return kind == CsmErrorProvider.EditorEvent.FileBased; + } + + @Override + public void doGetErrors(CsmErrorProvider.Request request, CsmErrorProvider.Response response) { + CsmFile file = request.getFile(); + if (file != null) { + if (request.isCancelled()) { + return; + } + + for (CsmReference ref : CsmReferenceResolver.getDefault().getReferences(file)) { + if (CsmKindUtilities.isFunction(ref.getReferencedObject())) { + CsmFunction function = (CsmFunction) ref.getReferencedObject(); + if (Checks.getInstance(level).isUnsecuredFunction(function)) { + String message = NbBundle.getMessage(UsingUnsafeFunctions.class + ,(level == Checks.Level.AVOID)?avoidDescription:avoidName); + CsmErrorInfo.Severity severity = toSeverity(minimalSeverity()); + if (response instanceof AnalyzerResponse) { + ((AnalyzerResponse) response).addError(AnalyzerResponse.AnalyzerSeverity.DetectedError, null, file.getFileObject(), + new ErrorInfoImpl(SecurityCheckProvider.NAME, getID(), getName()+"\n"+message, severity, ref.getStartOffset(), ref.getEndOffset())); // NOI18N + } else { + response.addError(new ErrorInfoImpl(SecurityCheckProvider.NAME, getID(), message, severity, ref.getStartOffset(), ref.getEndOffset())); + } + } + } + } + } + } + + @ServiceProvider(path = CodeAuditFactory.REGISTRATION_PATH+SecurityCheckProvider.NAME, service = CodeAuditFactory.class, position = 1300) + public static final class UnsafeFunctionsAuditFactory implements CodeAuditFactory { + @Override + public AbstractCodeAudit create(AuditPreferences preferences) { + String id = NbBundle.getMessage(UsingUnsafeFunctions.class, unsafeName); + String description = NbBundle.getMessage(UsingUnsafeFunctions.class, unsafeDescription); + return new UsingUnsafeFunctions(Checks.Level.UNSAFE, id, id, description, "error", true, preferences); // NOI18N + } + } + + @ServiceProvider(path = CodeAuditFactory.REGISTRATION_PATH+SecurityCheckProvider.NAME, service = CodeAuditFactory.class, position = 1300) + public static final class AvoidFunctionsAuditFactory implements CodeAuditFactory { + @Override + public AbstractCodeAudit create(AuditPreferences preferences) { + String id = NbBundle.getMessage(UsingUnsafeFunctions.class, avoidName); + String description = NbBundle.getMessage(UsingUnsafeFunctions.class, avoidDescription); + return new UsingUnsafeFunctions(Checks.Level.AVOID, id, id, description, "error", true, preferences); // NOI18N + } + } + +} diff --git a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/hints/SuggestionProvider.java b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/hints/SuggestionProvider.java --- a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/hints/SuggestionProvider.java +++ b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/hints/SuggestionProvider.java @@ -119,7 +119,7 @@ public synchronized Collection getAudits() { if (audits == null) { List res = new ArrayList<>(); - for(CodeAuditFactory factory : Lookups.forPath(CodeAuditFactory.REGISTRATION_PATH+NAME).lookupAll(CodeAuditFactory.class)) { + for(CodeAuditFactory factory : Lookups.forPath(CodeAuditFactory.REGISTRATION_PATH+SuggestionProvider.NAME).lookupAll(CodeAuditFactory.class)) { res.add(factory.create(myPreferences)); } Collections.sort(res, new Comparator(){