Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
8.3 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Copyright � 2001 Microsoft Corporation. All rights reserved.
  3. // PragmaUnsafeModule.cpp : Implementation of the CPragmaUnsafeModule class.
  4. //
  5. #include "stdafx.h"
  6. #include <pftAST.h>
  7. #include "PragmaUnsafeModule.h"
  8. #include "sxsplugMap.h"
  9. //
  10. // global variable
  11. //
  12. PragmaUnsafe_UNSAFE_FUNCTIONS Sxs_PragmaUnsafedFunctions;
  13. BOOL PragmaUnsafe_IsPossiblePointer(ICType * PtrSymbolType)
  14. {
  15. // case 1:
  16. // a pointer variable
  17. //
  18. if (PtrSymbolType->Kind() == TY_POINTER)
  19. return TRUE;
  20. // case 2:
  21. // a func return type is a pointer,
  22. //
  23. if (PtrSymbolType->Kind() == TY_FUNCTION)
  24. {
  25. //
  26. // check its return type
  27. //
  28. ICTypePtr spType;
  29. spType = PtrSymbolType->Returns();
  30. if ((spType != NULL) && (spType->Kind() == TY_POINTER))
  31. {
  32. return TRUE;
  33. }
  34. }
  35. return FALSE;
  36. }
  37. /////////////////////////////////////////////////////////////////////////////
  38. // Implementation
  39. //
  40. // Checks an individual tree node for errors.
  41. //
  42. void CPragmaUnsafeModule::CheckNode(ITree* pNode, DWORD level)
  43. {
  44. // Get the tree node kind and check for possible errors.
  45. AstNodeKind kind = pNode->Kind();
  46. // TODO: Add case statements to check for your defects
  47. switch (kind)
  48. {
  49. //
  50. // check pragma unsafe functions
  51. //
  52. case AST_FUNCTIONCALL:
  53. {
  54. if (pNode->IsCompilerGenerated() == VARIANT_FALSE)
  55. {
  56. // try to display the function name and its parameters:
  57. ITreePtr spFunction = skip_casts_and_parens(pNode->Child(0));
  58. _bstr_t bstrFunc= get_function_name(spFunction);
  59. if (bstrFunc.length() > 0)
  60. {
  61. if (FC_DIRECT == pNode->CallKind() || (FC_INTRINSIC == pNode->CallKind()))
  62. {
  63. if (FALSE == Sxs_PragmaUnsafedFunctions.IsFunctionNotUnsafe((char *)bstrFunc))
  64. {
  65. ReportDefectFmt(spFunction, WARNING_REPORT_UNSAFE_FUNCTIONCALL, static_cast<BSTR>(bstrFunc));
  66. //ReportDefect(pNode, WARNING_INVALID_PRAGMA_UNSAFE_STATEMENT);
  67. }
  68. }
  69. }
  70. }
  71. }
  72. break;
  73. //
  74. // declare pragma unsafe functions : disable, enable, push, pop
  75. //
  76. case AST_PRAGMA:
  77. {
  78. if ((pNode->Child(0) != NULL) && (pNode->Child(0)->Kind() == AST_STRING))
  79. {
  80. _bstr_t bstrStringValue = pNode->ExpressionValue();
  81. PRAGMA_STATEMENT ePragmaUnsafe;
  82. PragmaUnsafe_OnPragma((char *)bstrStringValue, ePragmaUnsafe);
  83. switch (ePragmaUnsafe){
  84. case PRAGMA_NOT_UNSAFE_STATEMENT:
  85. PragmaUnsafe_LogMessage("not a pragma unsafe\n");
  86. break;
  87. case PRAGMA_UNSAFE_STATEMENT_VALID:
  88. PragmaUnsafe_LogMessage("a valid a pragma unsafe\n");
  89. break;
  90. case PRAGMA_UNSAFE_STATEMENT_INVALID:
  91. ReportDefect(pNode, WARNING_INVALID_PRAGMA_UNSAFE_STATEMENT);
  92. break;
  93. } // end of switch (ePragmaUnsafe)
  94. }
  95. }
  96. break;
  97. //
  98. // pointer arithmatic : + , - * % \
  99. //
  100. case AST_PLUS:
  101. case AST_MINUS:
  102. case AST_MULT:
  103. case AST_DIV:
  104. case AST_REM:
  105. {
  106. //
  107. // check whether pointer is involved in the operation of its 2 children
  108. //
  109. for (DWORD i=0 ; i<2; i++)
  110. {
  111. ITreePtr subChildTreePtr = skip_parens(pNode->Child(i));
  112. if ((subChildTreePtr != NULL) && (subChildTreePtr->Kind() == AST_SYMBOL))
  113. {
  114. if ((subChildTreePtr->Symbol() != NULL) && (subChildTreePtr->Symbol()->Type() != NULL))
  115. {
  116. if (PragmaUnsafe_IsPossiblePointer(subChildTreePtr->Symbol()->Type()))
  117. {
  118. if (FALSE == PragmaUnsafe_IsPointerArithmaticEnabled())
  119. {
  120. ReportDefect(pNode, WARNING_REPORT_UNSAFE_POINTER_ARITHMATIC);
  121. }
  122. }
  123. }
  124. }
  125. }
  126. }
  127. break;
  128. default:
  129. break;
  130. } // end of switch (kind)
  131. }
  132. //
  133. // Traverses the tree rooted at pNode and calls CheckNode() on each node.
  134. //
  135. void CPragmaUnsafeModule::CheckNodeAndDescendants(ITree* pNode, DWORD level)
  136. {
  137. // Check if we need to abort.
  138. //CheckAbortAnalysis();
  139. // Do nothing if the specified node is NULL
  140. if (pNode == NULL)
  141. return;
  142. // Check the root for defects.
  143. CheckNode(pNode, level);
  144. // Get an iterator over the set of children.
  145. ITreeSetPtr spChildrenSet = pNode->Children();
  146. IEnumTreesPtr spChildrenEnum = spChildrenSet->_NewEnum();
  147. ITreePtr spCurrChild;
  148. // Iterate thru the children and recursively check them for errors.
  149. while (true)
  150. {
  151. long numReturned;
  152. spCurrChild = spChildrenEnum->Next(1, &numReturned);
  153. if (numReturned == 1)
  154. {
  155. CheckNodeAndDescendants(spCurrChild, level+1);
  156. }
  157. else
  158. {
  159. break;
  160. }
  161. }
  162. }
  163. /////////////////////////////////////////////////////////////////////////////
  164. // IPREfastModule Interface Methods
  165. //
  166. // No implementation.
  167. //
  168. STDMETHODIMP CPragmaUnsafeModule::raw_Events(AstEvents *Events)
  169. {
  170. *Events = static_cast<AstEvents>(EVENT_FUNCTION | EVENT_DIRECTIVE | EVENT_FILESTART | EVENT_FILE);
  171. return S_OK;
  172. }
  173. //
  174. // No implementation.
  175. //
  176. STDMETHODIMP CPragmaUnsafeModule::raw_OnFileStart(ICompilationUnit * pcu)
  177. {
  178. if (PragmaUnsafe_OnFileStart())
  179. return S_OK;
  180. else
  181. return E_FAIL;
  182. }
  183. //
  184. // No implementation.
  185. //
  186. STDMETHODIMP CPragmaUnsafeModule::raw_OnDeclaration(ICompilationUnit * pcu)
  187. {
  188. // Indicate success
  189. return S_OK;
  190. }
  191. //
  192. // No implementation.
  193. //
  194. STDMETHODIMP CPragmaUnsafeModule::raw_OnFileEnd(ICompilationUnit * pcu)
  195. {
  196. if (PragmaUnsafe_OnFileEnd())
  197. return S_OK;
  198. else
  199. return E_FAIL;
  200. }
  201. //
  202. // No implementation.
  203. //
  204. STDMETHODIMP CPragmaUnsafeModule::raw_OnDirective(ICompilationUnit * pcu)
  205. {
  206. if (pcu->Root()->Kind() != AST_PRAGMA)
  207. return S_OK;
  208. ITreePtr CurDirective = pcu->Root()->Child(0);
  209. if (CurDirective->Kind() != AST_STRING)
  210. {
  211. _bstr_t sKind = CurDirective->KindAsString();
  212. printf("the type is %s\n", (char *)sKind);
  213. return S_OK;
  214. }
  215. _bstr_t bstrStringValue = CurDirective->ExpressionValue();
  216. if (bstrStringValue.length() == 0)
  217. return S_OK;
  218. PRAGMA_STATEMENT ePragmaUnsafe;
  219. PragmaUnsafe_OnPragma((char *)bstrStringValue, ePragmaUnsafe);
  220. if ((ePragmaUnsafe == PRAGMA_NOT_UNSAFE_STATEMENT) || (ePragmaUnsafe == PRAGMA_UNSAFE_STATEMENT_VALID))
  221. return S_OK;
  222. else
  223. return E_FAIL;
  224. }
  225. //
  226. // Entry point for analysing functions.
  227. //
  228. STDMETHODIMP CPragmaUnsafeModule::raw_OnFunction(ICompilationUnit * icu)
  229. {
  230. // Save the function pointer for error reporting.
  231. m_spCurrFunction = icu->Root();
  232. cStartTimeOfFunction = GetTickCount();
  233. try
  234. {
  235. // Recursively check the function body.
  236. CheckNodeAndDescendants(m_spCurrFunction, 0);
  237. }
  238. catch (CAbortAnalysis)
  239. {
  240. // Ignore this exception and log all the others.
  241. printf("aborted\n");
  242. }
  243. // Release the objects.
  244. m_spCurrFunction = NULL;
  245. ClearDefectList();
  246. // Indicate success
  247. return S_OK;
  248. }