Source code of Windows XP (NT5)
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.

842 lines
23 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name :
  4. misc.c
  5. Abstract :
  6. Contains miscelaneous helper routines.
  7. Author :
  8. David Kays dkays December 1993.
  9. Revision History :
  10. ---------------------------------------------------------------------*/
  11. #include "ndrp.h"
  12. #include "attack.h"
  13. uchar *
  14. NdrpMemoryIncrement(
  15. PMIDL_STUB_MESSAGE pStubMsg,
  16. uchar * pMemory,
  17. PFORMAT_STRING pFormat
  18. )
  19. /*++
  20. Routine Description :
  21. Returns a memory pointer incremeted past a complex data type. This routine
  22. is also overloaded to compute the size of a complex data type by passing
  23. a 0 memory pointer.
  24. Arguments :
  25. pStubMsg - Pointer to the stub message.
  26. pMemory - Pointer to the complex type, or 0 if a size is being computed.
  27. pFormat - Format string description.
  28. Return :
  29. A memory pointer incremented past the complex type. If a 0 memory pointer
  30. was passed in then the returned value is the size of the complex type.
  31. --*/
  32. {
  33. long Elements;
  34. long ElementSize;
  35. switch ( *pFormat )
  36. {
  37. //
  38. // Structs
  39. //
  40. case FC_STRUCT :
  41. case FC_PSTRUCT :
  42. case FC_HARD_STRUCT :
  43. pMemory += *((ushort *)(pFormat + 2));
  44. break;
  45. case FC_CSTRUCT :
  46. case FC_CVSTRUCT :
  47. case FC_CPSTRUCT :
  48. pMemory += *((ushort *)(pFormat + 2));
  49. // Get conformant array or string description.
  50. pFormat += 4;
  51. pFormat += *((signed short *)pFormat);
  52. // This flag is set by the endianess pass only.
  53. if ( ! IS_TOPMOST_CONF_STRUCT( pStubMsg->uFlags ) )
  54. {
  55. // When embedding in a bogus struct, array is accounted
  56. // at the conf struct level, due to pointer layout.
  57. // Get the memory pointer past the conformant array.
  58. pMemory = NdrpMemoryIncrement( pStubMsg,
  59. pMemory,
  60. pFormat );
  61. }
  62. break;
  63. case FC_BOGUS_STRUCT :
  64. pMemory += *((ushort *)(pFormat + 2));
  65. pFormat += 4;
  66. // Check for a conformant array or string in the struct.
  67. if ( *((signed short *)pFormat) )
  68. {
  69. pFormat += *((signed short *)pFormat);
  70. if ( !IS_EMBED_CONF_STRUCT( pStubMsg->uFlags ) &&
  71. ! IS_CONF_ARRAY_DONE( pStubMsg->uFlags ) )
  72. {
  73. // Get the memory pointer past the conformant array.
  74. pMemory = NdrpMemoryIncrement( pStubMsg,
  75. pMemory,
  76. pFormat );
  77. }
  78. }
  79. break;
  80. //
  81. // Unions
  82. //
  83. case FC_ENCAPSULATED_UNION :
  84. pMemory += HIGH_NIBBLE(pFormat[1]);
  85. pMemory += *((ushort *)(pFormat + 2));
  86. break;
  87. case FC_NON_ENCAPSULATED_UNION :
  88. // Go to the size/arm description.
  89. pFormat += 6;
  90. CORRELATION_DESC_INCREMENT( pFormat );
  91. pFormat += *((signed short *)pFormat);
  92. pMemory += *((ushort *)pFormat);
  93. break;
  94. //
  95. // Arrays
  96. //
  97. case FC_SMFARRAY :
  98. case FC_SMVARRAY :
  99. pMemory += *((ushort *)(pFormat + 2));
  100. break;
  101. case FC_LGFARRAY :
  102. case FC_LGVARRAY :
  103. pMemory += *((ulong UNALIGNED *)(pFormat + 2));
  104. break;
  105. case FC_CARRAY:
  106. case FC_CVARRAY:
  107. {
  108. ULONG_PTR ConfSize = NdrpComputeConformance( pStubMsg,
  109. pMemory,
  110. pFormat);
  111. // check for possible mulitplication overflow attack here.
  112. pMemory += MultiplyWithOverflowCheck( ConfSize, *((ushort *)(pFormat + 2)) );
  113. }
  114. break;
  115. case FC_BOGUS_ARRAY :
  116. {
  117. PARRAY_INFO pArrayInfo = pStubMsg->pArrayInfo;
  118. if ( *((long UNALIGNED *)(pFormat + 4)) == 0xffffffff )
  119. Elements = *((ushort *)(pFormat + 2));
  120. else
  121. {
  122. if ( pArrayInfo &&
  123. pArrayInfo->MaxCountArray &&
  124. (pArrayInfo->MaxCountArray ==
  125. pArrayInfo->BufferConformanceMark) )
  126. {
  127. Elements = pArrayInfo->MaxCountArray[pArrayInfo->Dimension];
  128. }
  129. else
  130. {
  131. Elements = (ulong) NdrpComputeConformance( pStubMsg,
  132. pMemory,
  133. pFormat );
  134. }
  135. }
  136. // Go to the array element's description.
  137. pFormat += 12;
  138. CORRELATION_DESC_INCREMENT( pFormat );
  139. CORRELATION_DESC_INCREMENT( pFormat );
  140. //
  141. // Get the size of one element.
  142. //
  143. switch ( *pFormat )
  144. {
  145. case FC_ENUM16 :
  146. ElementSize = sizeof(int);
  147. break;
  148. case FC_RP :
  149. case FC_UP :
  150. case FC_FP :
  151. case FC_OP :
  152. ElementSize = PTR_MEM_SIZE;
  153. break;
  154. case FC_EMBEDDED_COMPLEX :
  155. //
  156. // It's some complicated thingy.
  157. //
  158. pFormat += 2;
  159. pFormat += *((signed short *)pFormat);
  160. if ( (*pFormat == FC_TRANSMIT_AS) ||
  161. (*pFormat == FC_REPRESENT_AS) ||
  162. (*pFormat == FC_USER_MARSHAL) )
  163. {
  164. //
  165. // Get the presented type size.
  166. //
  167. ElementSize = *((ushort *)(pFormat + 4));
  168. }
  169. else
  170. {
  171. if ( pArrayInfo )
  172. pArrayInfo->Dimension++;
  173. ElementSize = (long)
  174. ( NdrpMemoryIncrement( pStubMsg,
  175. pMemory,
  176. pFormat ) - pMemory );
  177. if ( pArrayInfo )
  178. pArrayInfo->Dimension--;
  179. }
  180. break;
  181. case FC_RANGE:
  182. ElementSize = SIMPLE_TYPE_MEMSIZE( (pFormat[1] & 0x0f) );
  183. break;
  184. default :
  185. if ( IS_SIMPLE_TYPE(*pFormat) )
  186. {
  187. ElementSize = SIMPLE_TYPE_MEMSIZE(*pFormat);
  188. break;
  189. }
  190. NDR_ASSERT(0,"NdrpMemoryIncrement : bad format char");
  191. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  192. return 0;
  193. }
  194. // check for possible mulitplication overflow attack here.
  195. pMemory += MultiplyWithOverflowCheck( Elements, ElementSize );
  196. }
  197. break;
  198. //
  199. // String arrays (a.k.a. non-conformant strings).
  200. //
  201. case FC_CSTRING :
  202. case FC_BSTRING :
  203. case FC_WSTRING :
  204. {
  205. ULONG ElementSize = (*pFormat == FC_WSTRING) ? sizeof(wchar_t) : sizeof(char) ;
  206. ULONG Elements = *((ushort *)(pFormat + 2)) ;
  207. // check for possible mulitplication overflow attack here.
  208. pMemory += MultiplyWithOverflowCheck( Elements, ElementSize );
  209. }
  210. break;
  211. case FC_SSTRING :
  212. // check for possible mulitplication overflow attack here.
  213. pMemory += MultiplyWithOverflowCheck( pFormat[1], *((ushort *)(pFormat + 2) ) );
  214. break;
  215. //
  216. // Sized conformant strings.
  217. //
  218. case FC_C_CSTRING:
  219. case FC_C_BSTRING:
  220. case FC_C_WSTRING:
  221. {
  222. PARRAY_INFO pArrayInfo = pStubMsg->pArrayInfo;
  223. ULONG ElementSize = (*pFormat == FC_C_WSTRING) ?
  224. sizeof(wchar_t) :
  225. sizeof(char);
  226. NDR_ASSERT(pFormat[1] == FC_STRING_SIZED,
  227. "NdrpMemoryIncrement : called for non-sized string");
  228. if ( pArrayInfo &&
  229. pArrayInfo->MaxCountArray &&
  230. (pArrayInfo->MaxCountArray ==
  231. pArrayInfo->BufferConformanceMark) )
  232. {
  233. Elements = pArrayInfo->MaxCountArray[pArrayInfo->Dimension];
  234. }
  235. else
  236. {
  237. Elements = (ulong) NdrpComputeConformance( pStubMsg,
  238. pMemory,
  239. pFormat );
  240. }
  241. // check for possible mulitplication overflow attack here.
  242. pMemory += MultiplyWithOverflowCheck( Elements, ElementSize );
  243. }
  244. break;
  245. case FC_C_SSTRING:
  246. {
  247. PARRAY_INFO pArrayInfo = pStubMsg->pArrayInfo;
  248. if ( pArrayInfo &&
  249. pArrayInfo->MaxCountArray &&
  250. (pArrayInfo->MaxCountArray ==
  251. pArrayInfo->BufferConformanceMark) )
  252. {
  253. Elements = pArrayInfo->MaxCountArray[pArrayInfo->Dimension];
  254. }
  255. else
  256. {
  257. Elements = (ulong) NdrpComputeConformance( pStubMsg,
  258. pMemory,
  259. pFormat );
  260. }
  261. // check for possible mulitplication overflow attack here.
  262. pMemory += MultiplyWithOverflowCheck( Elements, pFormat[1] );
  263. }
  264. break;
  265. //
  266. // Transmit as, represent as, user marshal
  267. //
  268. case FC_TRANSMIT_AS :
  269. case FC_REPRESENT_AS :
  270. case FC_USER_MARSHAL :
  271. // Get the presented type size.
  272. pMemory += *((ushort *)(pFormat + 4));
  273. break;
  274. case FC_BYTE_COUNT_POINTER:
  275. //
  276. // Should only hit this case when called from NdrSrvOutInit().
  277. // In this case it's the total byte count allocation size we're
  278. // looking for.
  279. //
  280. // We are taking the larger of conformant size and the real data
  281. // type size, otherwise, we might give user a partially invalid
  282. // buffer, and that'll come back to bite us during sizing/marshalling
  283. {
  284. uchar * pMemory1 = pMemory;
  285. uchar * pMemory2 = pMemory;
  286. PFORMAT_STRING pFormat2 = pFormat;
  287. if ( pFormat[1] != FC_PAD )
  288. {
  289. pMemory2 += SIMPLE_TYPE_MEMSIZE( pFormat[1] );
  290. }
  291. else
  292. {
  293. // go pass the conformance & get to the real type
  294. pFormat2 += 6;
  295. CORRELATION_DESC_INCREMENT( pFormat2 );
  296. pFormat2 += *((signed short *)pFormat2);
  297. pMemory2 = NdrpMemoryIncrement( pStubMsg,
  298. pMemory2,
  299. pFormat2 );
  300. }
  301. pMemory1 += NdrpComputeConformance( pStubMsg,
  302. pMemory1,
  303. pFormat );
  304. pMemory = ( pMemory1 > pMemory2 )? pMemory1 : pMemory2;
  305. break;
  306. }
  307. case FC_IP :
  308. pMemory += PTR_MEM_SIZE;
  309. break;
  310. case FC_RANGE:
  311. pMemory += SIMPLE_TYPE_MEMSIZE( (pFormat[1] & 0x0f) );
  312. break;
  313. #ifdef _CS_CHAR_
  314. case FC_CSARRAY:
  315. {
  316. uchar * OldBuffer = pStubMsg->Buffer;
  317. ulong OldSize = pStubMsg->MemorySize;
  318. pStubMsg->MemorySize = 0;
  319. pMemory += NdrCsArrayMemorySize( pStubMsg, pFormat );
  320. pStubMsg->MemorySize = OldSize;
  321. pStubMsg->Buffer = OldBuffer;
  322. break;
  323. }
  324. case FC_CS_TAG:
  325. pMemory += sizeof( ulong );
  326. break;
  327. #endif _CS_CHAR_
  328. default :
  329. NDR_ASSERT(0,"NdrpMemoryIncrement : bad format char");
  330. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  331. return 0;
  332. }
  333. return pMemory;
  334. }
  335. long
  336. NdrpArrayDimensions(
  337. PMIDL_STUB_MESSAGE pStubMsg,
  338. PFORMAT_STRING pFormat,
  339. BOOL fIgnoreStringArrays
  340. )
  341. /*++
  342. Routine description :
  343. This routine determines the number of dimensions in a complex array, which
  344. is the only array type which is allowed to have multiple dimensions other
  345. than an array of multiple fixed dimensions.
  346. Arguments :
  347. pFormat - Complex array's format string description.
  348. fIgnoreStringArrays - TRUE if a string array should not be counted as
  349. a dimension, FALSE if it should.
  350. Return :
  351. The number of dimensions in the array.
  352. --*/
  353. {
  354. long Dimensions;
  355. //
  356. // Only a complex array can have multiple dimensions.
  357. //
  358. if ( *pFormat != FC_BOGUS_ARRAY )
  359. return 1;
  360. Dimensions = 1;
  361. pFormat += 12;
  362. CORRELATION_DESC_INCREMENT( pFormat );
  363. CORRELATION_DESC_INCREMENT( pFormat );
  364. for ( ; *pFormat == FC_EMBEDDED_COMPLEX; )
  365. {
  366. pFormat += 2;
  367. pFormat += *((signed short *)pFormat);
  368. //
  369. // Search for a fixed, complex, or string array.
  370. //
  371. switch ( *pFormat )
  372. {
  373. case FC_SMFARRAY :
  374. pFormat += 4;
  375. break;
  376. case FC_LGFARRAY :
  377. pFormat += 6;
  378. break;
  379. case FC_BOGUS_ARRAY :
  380. pFormat += 12;
  381. CORRELATION_DESC_INCREMENT( pFormat );
  382. CORRELATION_DESC_INCREMENT( pFormat );
  383. break;
  384. case FC_CSTRING :
  385. case FC_BSTRING :
  386. case FC_WSTRING :
  387. case FC_SSTRING :
  388. case FC_C_CSTRING :
  389. case FC_C_BSTRING :
  390. case FC_C_WSTRING :
  391. case FC_C_SSTRING :
  392. //
  393. // Can't have any more dimensions after a string array.
  394. //
  395. return fIgnoreStringArrays ? Dimensions : Dimensions + 1;
  396. default :
  397. return Dimensions;
  398. }
  399. Dimensions++;
  400. }
  401. //
  402. // Get here if you have only one dimension.
  403. //
  404. return Dimensions;
  405. }
  406. long
  407. NdrpArrayElements(
  408. PMIDL_STUB_MESSAGE pStubMsg,
  409. uchar * pMemory,
  410. PFORMAT_STRING pFormat
  411. )
  412. /*++
  413. Routine description :
  414. This routine determines the number of elements (allocation size) in an
  415. array. Used to handle multidimensional arrays.
  416. Arguments :
  417. pStubMsg - The stub message.
  418. pMemory - The array.
  419. pFormat - Array's format string description.
  420. Return :
  421. The number of elements in the array.
  422. --*/
  423. {
  424. long TotalSize;
  425. long ElementSize;
  426. switch ( *pFormat )
  427. {
  428. case FC_SMFARRAY :
  429. TotalSize = (long) *((ushort *)(pFormat + 2));
  430. pFormat += 4;
  431. break;
  432. case FC_LGFARRAY :
  433. TotalSize = *((long UNALIGNED *)(pFormat + 2));
  434. pFormat += 6;
  435. break;
  436. case FC_SMVARRAY :
  437. return (long) *((ushort *)(pFormat + 4));
  438. case FC_LGVARRAY :
  439. return *((long UNALIGNED *)(pFormat + 6));
  440. case FC_BOGUS_ARRAY :
  441. if ( *((long *)(pFormat + 4)) == 0xffffffff )
  442. return (long) *((ushort *)(pFormat + 2));
  443. // else fall through
  444. case FC_CARRAY :
  445. case FC_CVARRAY :
  446. return (ulong) NdrpComputeConformance( pStubMsg,
  447. pMemory,
  448. pFormat );
  449. default :
  450. NDR_ASSERT(0,"NdrpArrayElements : bad format char");
  451. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  452. return 0;
  453. }
  454. //
  455. // We get here for a non-complex fixed array.
  456. //
  457. // Since a fixed array's format string description does not
  458. // contain the number of elements in the array, we have to compute
  459. // it by computing the array's element size and dividing this into
  460. // the total array size.
  461. //
  462. // A fixed array's child can only be a nice struct, another
  463. // fixed array, a pointer, or a simple type.
  464. //
  465. //
  466. // Skip pointer layout if one is present.
  467. //
  468. if ( *pFormat == FC_PP )
  469. pFormat = NdrpSkipPointerLayout( pFormat );
  470. switch ( *pFormat )
  471. {
  472. case FC_EMBEDDED_COMPLEX :
  473. pFormat += 2;
  474. pFormat += *((signed short *)pFormat);
  475. //
  476. // We must be at FC_STRUCT, FC_PSTRUCT, FC_SMFARRAY, or FC_LGFARRAY.
  477. // All these have the total size as a short at 2 bytes past the
  478. // beginning of the description except for large fixed array.
  479. //
  480. if ( *pFormat != FC_LGFARRAY )
  481. ElementSize = (long) *((ushort *)(pFormat + 2));
  482. else
  483. ElementSize = *((long UNALIGNED *)(pFormat + 2));
  484. break;
  485. //
  486. // Simple type (enum16 not possible).
  487. //
  488. default :
  489. ElementSize = SIMPLE_TYPE_MEMSIZE( *pFormat );
  490. break;
  491. }
  492. return TotalSize / ElementSize;
  493. }
  494. void
  495. NdrpArrayVariance(
  496. PMIDL_STUB_MESSAGE pStubMsg,
  497. uchar * pMemory,
  498. PFORMAT_STRING pFormat,
  499. long * pOffset,
  500. long * pLength
  501. )
  502. /*++
  503. Routine description :
  504. This routine determines the offset and length values for an array.
  505. Used to handle multidimensional arrays.
  506. Arguments :
  507. pStubMsg - The stub message.
  508. pMemory - The array.
  509. pFormat - Array's format string description.
  510. pOffset - Returned offset value.
  511. pLength - Returned length value.
  512. Return :
  513. None.
  514. --*/
  515. {
  516. switch ( *pFormat )
  517. {
  518. case FC_SMFARRAY :
  519. case FC_LGFARRAY :
  520. case FC_CARRAY :
  521. *pOffset = 0;
  522. *pLength = NdrpArrayElements( pStubMsg,
  523. pMemory,
  524. pFormat );
  525. break;
  526. case FC_BOGUS_ARRAY :
  527. {
  528. PFORMAT_STRING pFormatBAV = pFormat + 8;
  529. CORRELATION_DESC_INCREMENT( pFormatBAV );
  530. if ( *((long UNALIGNED *)(pFormatBAV + 8)) == 0xffffffff )
  531. {
  532. *pOffset = 0;
  533. *pLength = NdrpArrayElements( pStubMsg,
  534. pMemory,
  535. pFormat );
  536. return;
  537. }
  538. }
  539. // else fall through
  540. case FC_CVARRAY :
  541. case FC_SMVARRAY :
  542. case FC_LGVARRAY :
  543. NdrpComputeVariance( pStubMsg,
  544. pMemory,
  545. pFormat );
  546. *pOffset = (long) pStubMsg->Offset;
  547. *pLength = (long) pStubMsg->ActualCount;
  548. break;
  549. default :
  550. NDR_ASSERT(0,"NdrpArrayVariance : bad format char");
  551. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  552. return;
  553. }
  554. }
  555. PFORMAT_STRING
  556. NdrpSkipPointerLayout(
  557. PFORMAT_STRING pFormat
  558. )
  559. /*--
  560. RoutineDescription :
  561. Skips a pointer layout format string description.
  562. Arguments :
  563. pFormat - Format string pointer layout description. Must currently
  564. point to the FC_PP beginning the pointer layout.
  565. Return :
  566. Format string pointer past the pointer layout.
  567. --*/
  568. {
  569. long Pointers;
  570. NDR_ASSERT( *pFormat == FC_PP,
  571. "NdrpSkipPointerLayout : format string not at FC_PP" );
  572. // Skip FC_PP and FC_PAD.
  573. pFormat += 2;
  574. for (;;)
  575. {
  576. switch ( *pFormat )
  577. {
  578. case FC_END :
  579. return pFormat + 1;
  580. case FC_NO_REPEAT :
  581. pFormat += 10;
  582. break;
  583. case FC_FIXED_REPEAT :
  584. pFormat += 2;
  585. // fall through...
  586. case FC_VARIABLE_REPEAT :
  587. pFormat += 6;
  588. Pointers = *((ushort * &)pFormat)++;
  589. pFormat += Pointers * 8;
  590. break;
  591. default :
  592. NDR_ASSERT( 0, "NdrpSkipPointerLayout : bad format char" );
  593. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  594. return 0;
  595. }
  596. }
  597. }
  598. long
  599. NdrpStringStructLen(
  600. uchar * pMemory,
  601. long ElementSize
  602. )
  603. /*--
  604. RoutineDescription :
  605. Determines a stringable struct's length.
  606. Arguments :
  607. pMemory - Pointer to stringable struct.
  608. ElementSize - Number of bytes of each string element.
  609. Return :
  610. Length of string.
  611. --*/
  612. {
  613. long Length;
  614. uchar Buffer[256];
  615. // Note : String struct element size is limited to 256 bytes.
  616. MIDL_memset( Buffer, 0, 256 );
  617. for ( Length = 0; ; Length++ )
  618. {
  619. if ( memcmp( pMemory, Buffer, ElementSize ) == 0 )
  620. break;
  621. pMemory += ElementSize;
  622. }
  623. return Length;
  624. }
  625. void
  626. NdrpCheckBound(
  627. ulong Bound,
  628. int Type
  629. )
  630. {
  631. ulong Mask;
  632. switch ( Type )
  633. {
  634. case FC_ULONG :
  635. #if defined(__RPC_WIN64__)
  636. case FC_UINT3264 :
  637. case FC_INT3264 :
  638. #endif
  639. //
  640. // We use a mask here which will raise an exception for counts
  641. // of 2GB or more since this is the max NT allocation size.
  642. //
  643. Mask = 0x80000000UL;
  644. break;
  645. case FC_LONG :
  646. Mask = 0x80000000UL;
  647. break;
  648. case FC_USHORT :
  649. Mask = 0xffff0000UL;
  650. break;
  651. case FC_SHORT :
  652. Mask = 0xffff8000UL;
  653. break;
  654. case FC_USMALL :
  655. Mask = 0xffffff00UL;
  656. break;
  657. case FC_SMALL :
  658. Mask = 0xffffff80UL;
  659. break;
  660. case 0 :
  661. //
  662. // For variance which requires calling an auxilary expression
  663. // evaluation routine a type is not emitted in the format string.
  664. // We have to just give up.
  665. //
  666. // The same thing happens with constant conformance type
  667. // we emit zero on the var type nibble.
  668. //
  669. return;
  670. default :
  671. NDR_ASSERT( 0, "NdrpCheckBound : bad type" );
  672. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  673. return;
  674. }
  675. if ( Bound & Mask )
  676. RpcRaiseException( RPC_X_INVALID_BOUND );
  677. }