srcanamdw/codescanner/scripts/forgottoputptroncleanupstack.py
changeset 1 22878952f6e2
equal deleted inserted replaced
0:509e4801c378 1:22878952f6e2
       
     1 # #################################################################
       
     2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # 
       
     5 # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
       
     6 # 
       
     7 # * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
       
     8 # * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
       
     9 # * Neither the name of Nokia Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
       
    10 # 
       
    11 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
       
    12 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 
       
    13 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
       
    14 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
       
    15 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#
       
    16 #
       
    17 # forgottoputptroncleanupstack.py
       
    18 #
       
    19 # Checks : Neglected to put variable on cleanup stack.
       
    20 #
       
    21 # Reason : If a variable is not put on the cleanup stack and a 
       
    22 # leaving function or ELeave is called, a memory leak occurs. 
       
    23 # CodeScanner occasionally gives false positives for this issue. 
       
    24 # Individual cases should be investigated.
       
    25 #
       
    26 # #################################################################
       
    27 
       
    28 script = CScript("forgottoputptroncleanupstack")
       
    29 script.iReString = r"""
       
    30 	\s+				# optional whitespace
       
    31 	[b-hj-z]+		# must not be a member or parameter
       
    32 	[A-Za-z0-9]+	# variable name
       
    33 	\s*				# optional whitespace
       
    34 	=				# assignment operator
       
    35 	"""
       
    36 script.iFileExts = ["cpp"]
       
    37 script.iCategory = KCategoryCodeReviewGuides
       
    38 script.iIgnore = KIgnoreCommentsAndQuotes
       
    39 script.iSeverity = KSeverityLow
       
    40 
       
    41 forgottoputptroncleanupstackCleanup = re.compile("""Cleanup""", re.VERBOSE)
       
    42 
       
    43 forgottoputptroncleanupstackDeleteOp = re.compile("""
       
    44 	\s+
       
    45 	delete
       
    46 	\s+
       
    47 	""", re.VERBOSE)
       
    48 
       
    49 forgottoputptroncleanupstackReturnCmd = re.compile("""
       
    50 	(\s*|\()
       
    51 	return
       
    52 	(\s*|\()
       
    53 	""", re.VERBOSE)
       
    54 
       
    55 forgottoputptroncleanupstackSetFn = re.compile("""
       
    56 	Set
       
    57 	[A-Za-z0-9]+
       
    58 	[A-KM-Za-z0-9]
       
    59 	\s*
       
    60 	\(
       
    61 	""", re.VERBOSE)
       
    62 
       
    63 forgottoputptroncleanupstackBreak = re.compile("""
       
    64 	\s+
       
    65 	break
       
    66 	\s*
       
    67 	;
       
    68 	""", re.VERBOSE)
       
    69 
       
    70 forgottoputptroncleanupstackIf = re.compile("""
       
    71 	\s+
       
    72 	if
       
    73 	\s*
       
    74 	\(
       
    75 	""", re.VERBOSE)
       
    76 	
       
    77 forgottoputptroncleanupstackElse = re.compile("""
       
    78 	\}*
       
    79 	\s*
       
    80 	else
       
    81 	\s*
       
    82 	\{*
       
    83 	""", re.VERBOSE)
       
    84 
       
    85 forgottoputptroncleanupstackAssignToMember = re.compile("""
       
    86 	i
       
    87 	[A-Za-z0-9\[\]]+
       
    88 	\s*
       
    89 	=
       
    90 	\s*
       
    91 	.*
       
    92 	\s*
       
    93 	;
       
    94 	""", re.VERBOSE)
       
    95 
       
    96 forgottoputptroncleanupstackTrapMacro = re.compile("""
       
    97 	TRAP
       
    98 	[D]*
       
    99 	\s*
       
   100 	\(
       
   101 	""", re.VERBOSE)
       
   102 
       
   103 forgottoputptroncleanupstackLeavingFunction = re.compile("""
       
   104 	[A-Za-z0-9]+
       
   105 	L
       
   106 	\s*
       
   107 	\(
       
   108 	""", re.VERBOSE)
       
   109 
       
   110 forgottoputptroncleanupstackLeave = re.compile("""
       
   111 	User::Leave
       
   112 	""", re.VERBOSE)
       
   113 
       
   114 forgottoputptroncleanupstackLeaveAndDelete = re.compile("""
       
   115 	L
       
   116 	[D]+
       
   117 	\s*
       
   118 	\(
       
   119 	""", re.VERBOSE)
       
   120 
       
   121 forgottoputptroncleanupstackNewOperator = re.compile("""
       
   122 	new
       
   123 	\s*
       
   124 	\(
       
   125 	\s*
       
   126 	ELeave
       
   127 	""", re.VERBOSE)
       
   128 
       
   129 forgottoputptroncleanupstackNewFunction = re.compile("""
       
   130 	::NewL
       
   131 	\s*
       
   132 	\(
       
   133 	""", re.VERBOSE)
       
   134 
       
   135 forgottoputptroncleanupstackCreateFunction = re.compile("""
       
   136 	Create
       
   137 	[A-Za-z0-9]+
       
   138 	L
       
   139 	\s*
       
   140 	\(
       
   141 	""", re.VERBOSE)
       
   142 
       
   143 forgottoputptroncleanupstackAllocFunction = re.compile("""
       
   144 	Alloc
       
   145 	L*
       
   146 	\s*
       
   147 	\(
       
   148 	""", re.VERBOSE)
       
   149 
       
   150 def findForgetCompare(lines, currentline, rematch, filename):
       
   151 	line = lines[currentline]
       
   152 	m = rematch.search(line)
       
   153 
       
   154 	if m:
       
   155 		foundNew = 0
       
   156 		equalPos = line.find("=")
       
   157 		assignedSection = line[equalPos:]
       
   158 	
       
   159 		if forgottoputptroncleanupstackNewFunction.search(assignedSection):
       
   160 			foundNew = 1
       
   161 		if forgottoputptroncleanupstackNewOperator.search(assignedSection):
       
   162 			foundNew = 1
       
   163 		if forgottoputptroncleanupstackAllocFunction.search(assignedSection):
       
   164 			foundNew = 1
       
   165 		if forgottoputptroncleanupstackCreateFunction.search(assignedSection):
       
   166 			foundNew = 1
       
   167 
       
   168 		# if this line contains a 'new', a 'NewL(', or an 'AllocL('
       
   169 		if (foundNew == 1):	
       
   170 			i = currentline
       
   171 
       
   172 		# move to next line ending if this line doesn't contain one
       
   173 			while (lines[i].find(';') == -1):
       
   174 				i = i + 1
       
   175 
       
   176 		# go to next line
       
   177 			i = i + 1
       
   178 			bracketdepth = GetBracketDepth(lines, i)
       
   179 			
       
   180 		# get the variable name, between the '*' and the '='
       
   181 			startindex = line.find("*")
       
   182 			if (startindex == -1):
       
   183 				startindex = 0
       
   184 			endindex = line.find("=")
       
   185 			variable = line[startindex+1:endindex]
       
   186 			if (len(variable) < 1):
       
   187 				return 0
       
   188 			variable = TrimVariableName(variable)
       
   189 
       
   190 			inAnIfOrSelectStatement = 1 # possibly
       
   191 			
       
   192 			while (i < len(lines)):
       
   193 				line2 = lines[i]
       
   194 
       
   195 				if (line2.find('{') >= 0):
       
   196 					bracketdepth = bracketdepth + 1
       
   197 				if (line2.find('}') >= 0):
       
   198 					bracketdepth = bracketdepth - 1
       
   199 					inAnIfOrSelectStatement = 0
       
   200 					if (bracketdepth == 0):
       
   201 						return 0
       
   202 
       
   203 				varIndex = line2.find(variable)
       
   204 		# if a later line contains the variable...
       
   205 				while (varIndex <> -1):
       
   206 					if (isNonAlpha(line2[varIndex-1])):
       
   207 						if (isNonAlpha(line2[varIndex+len(variable)])):
       
   208 		# ...and delete, exit
       
   209 							if forgottoputptroncleanupstackDeleteOp.search(line2):
       
   210 								return 0
       
   211 	
       
   212 		# ...and an xxxLD() function, exit
       
   213 							if forgottoputptroncleanupstackLeaveAndDelete.search(line2):
       
   214 								return 0
       
   215 							
       
   216 		# ...and the variable is assigned to a member variable, exit
       
   217 							if forgottoputptroncleanupstackAssignToMember.search(line2):
       
   218 								return 0
       
   219 		
       
   220 		# ...and it is a Set...() call, exit (e.g. SetArray, SetAppUi)
       
   221 							if forgottoputptroncleanupstackSetFn.search(line2):
       
   222 								return 0
       
   223 
       
   224 		# ...and a return command, exit 
       
   225 							if forgottoputptroncleanupstackReturnCmd.search(line2):
       
   226 								return 0
       
   227 
       
   228 		# search this line again incase there are similarly named variables
       
   229 					line2 = line2[varIndex+1:]
       
   230 					varIndex = line2.find(variable)
       
   231 
       
   232 				line2 = lines[i]
       
   233 		# if a leaving function is called...
       
   234 				if forgottoputptroncleanupstackLeavingFunction.search(line2):
       
   235 		# ...if the leaving function is trapped, exit
       
   236 					if forgottoputptroncleanupstackTrapMacro.search(line2):
       
   237 						return 0
       
   238 		# ...if a Cleanup function is called, exit
       
   239 					if forgottoputptroncleanupstackCleanup.search(line2):
       
   240 						return 0
       
   241 		# ...otherwise this is a problem!
       
   242 					return 1
       
   243 
       
   244 		# if a User::Leave is called, this is a problem
       
   245 				if forgottoputptroncleanupstackLeave.search(line2):
       
   246 					return 1
       
   247 	
       
   248 		# if the variable is initialised in a branch of an 'if' or 'switch' statement, ignore other branches
       
   249 				if (inAnIfOrSelectStatement == 1):
       
   250 					if forgottoputptroncleanupstackBreak.search(line2):
       
   251 						atLine = i
       
   252 						inAnIfOrSelectStatement = 0
       
   253 						findSwitch = i
       
   254 						line3 = lines[findSwitch]
       
   255 						while (line3.find("switch") == -1):
       
   256 							findSwitch = findSwitch - 1
       
   257 							if (findSwitch <= 0):
       
   258 								return 0
       
   259 							line3 = lines[findSwitch]
       
   260 						switchBracketDepth = GetBracketDepth(lines, findSwitch)
       
   261 						i = atLine
       
   262 						while (bracketdepth > switchBracketDepth):
       
   263 							if (i >= len(lines)):
       
   264 								return 0
       
   265 							line2 = lines[i]
       
   266 							if (line2.find('{') >= 0):
       
   267 								bracketdepth = bracketdepth + 1
       
   268 							if (line2.find('}') >= 0):
       
   269 								bracketdepth = bracketdepth - 1
       
   270 							i = i + 1
       
   271 							
       
   272 					if forgottoputptroncleanupstackElse.search(line2):
       
   273 						inAnIfOrSelectStatement = 0
       
   274 						elseBracketDepth = bracketdepth
       
   275 						if (line2.find('{') >= 0):
       
   276 							elseBracketDepth = elseBracketDepth - 1
       
   277 						if (elseBracketDepth == GetBracketDepth(lines, currentline)):
       
   278 							while (line2.find(';') == -1):
       
   279 								i = i + 1
       
   280 								if (i >= len(lines)):
       
   281 									return 0
       
   282 								line2 = lines[i]
       
   283 						else:
       
   284 							while (bracketdepth > elseBracketDepth):
       
   285 								i = i + 1
       
   286 								if (i >= len(lines)):
       
   287 									return 0
       
   288 								line2 = lines[i]
       
   289 								if (line2.find('{') >= 0):
       
   290 									bracketdepth = bracketdepth + 1
       
   291 								if (line2.find('}') >= 0):
       
   292 									bracketdepth = bracketdepth - 1
       
   293 
       
   294 					if forgottoputptroncleanupstackIf.search(line2):
       
   295 						inAnIfOrSelectStatement = 0
       
   296 				i = i + 1
       
   297 			return 0
       
   298 
       
   299 	return 0
       
   300 
       
   301 script.iCompare	= findForgetCompare
       
   302 scanner.AddScript(script)