mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-31 10:40:34 +00:00 
			
		
		
		
	 04c30dd571
			
		
	
	
		04c30dd571
		
	
	
	
	
		
			
			In UEFI2.6, CapturePtr's in the Captures array returned by MatchString are to be separatedly allocated so that they can be freed by the caller. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Cecil Sheng <cecil.sheng@hpe.com> Reviewed-by: Samer El-Haj-Mahmoud <elhaj@hpe.com> Reviewed-by: Star Zeng <star.zeng@intel.com>
		
			
				
	
	
		
			388 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			388 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| 
 | |
|   EFI_REGULAR_EXPRESSION_PROTOCOL Implementation
 | |
| 
 | |
|   (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
 | |
| 
 | |
|   This program and the accompanying materials are licensed and made available
 | |
|   under the terms and conditions of the BSD License that accompanies this
 | |
|   distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php.
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
 | |
|   WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "RegularExpressionDxe.h"
 | |
| 
 | |
| STATIC
 | |
| EFI_REGEX_SYNTAX_TYPE * CONST mSupportedSyntaxes[] = {
 | |
|   &gEfiRegexSyntaxTypePosixExtendedGuid,
 | |
|   &gEfiRegexSyntaxTypePerlGuid
 | |
| };
 | |
| 
 | |
| STATIC
 | |
| EFI_REGULAR_EXPRESSION_PROTOCOL mProtocolInstance = {
 | |
|   RegularExpressionMatch,
 | |
|   RegularExpressionGetInfo
 | |
| };
 | |
| 
 | |
| 
 | |
| 
 | |
| #define CHAR16_ENCODING ONIG_ENCODING_UTF16_LE
 | |
| 
 | |
| /**
 | |
|   Call the Oniguruma regex match API.
 | |
| 
 | |
|   Same parameters as RegularExpressionMatch, except SyntaxType is required.
 | |
| 
 | |
|   @param String         A pointer to a NULL terminated string to match against the
 | |
|                         regular expression string specified by Pattern.
 | |
| 
 | |
|   @param Pattern        A pointer to a NULL terminated string that represents the
 | |
|                         regular expression.
 | |
|   @param SyntaxType     A pointer to the EFI_REGEX_SYNTAX_TYPE that identifies the
 | |
|                         regular expression syntax type to use. May be NULL in which
 | |
|                         case the function will use its default regular expression
 | |
|                         syntax type.
 | |
| 
 | |
|   @param Result         On return, points to TRUE if String fully matches against
 | |
|                         the regular expression Pattern using the regular expression
 | |
|                         SyntaxType. Otherwise, points to FALSE.
 | |
| 
 | |
|   @param Captures       A Pointer to an array of EFI_REGEX_CAPTURE objects to receive
 | |
|                         the captured groups in the event of a match. The full
 | |
|                         sub-string match is put in Captures[0], and the results of N
 | |
|                         capturing groups are put in Captures[1:N]. If Captures is
 | |
|                         NULL, then this function doesn't allocate the memory for the
 | |
|                         array and does not build up the elements. It only returns the
 | |
|                         number of matching patterns in CapturesCount. If Captures is
 | |
|                         not NULL, this function returns a pointer to an array and
 | |
|                         builds up the elements in the array. CapturesCount is also
 | |
|                         updated to the number of matching patterns found. It is the
 | |
|                         caller's responsibility to free the memory pool in Captures
 | |
|                         and in each CapturePtr in the array elements.
 | |
| 
 | |
|   @param CapturesCount  On output, CapturesCount is the number of matching patterns
 | |
|                         found in String. Zero means no matching patterns were found
 | |
|                         in the string.
 | |
| 
 | |
|   @retval  EFI_SUCCESS       Regex compilation and match completed successfully.
 | |
|   @retval  EFI_DEVICE_ERROR  Regex compilation failed.
 | |
| 
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| OnigurumaMatch (
 | |
|   IN  CHAR16                *String,
 | |
|   IN  CHAR16                *Pattern,
 | |
|   IN  EFI_REGEX_SYNTAX_TYPE *SyntaxType,
 | |
|   OUT BOOLEAN               *Result,
 | |
|   OUT EFI_REGEX_CAPTURE     **Captures,     OPTIONAL
 | |
|   OUT UINTN                 *CapturesCount
 | |
|   )
 | |
| {
 | |
|   regex_t         *OnigRegex;
 | |
|   OnigSyntaxType  *OnigSyntax;
 | |
|   OnigRegion      *Region;
 | |
|   INT32           OnigResult;
 | |
|   OnigErrorInfo   ErrorInfo;
 | |
|   CHAR8           ErrorMessage[ONIG_MAX_ERROR_MESSAGE_LEN];
 | |
|   UINT32          Index;
 | |
|   OnigUChar       *Start;
 | |
|   EFI_STATUS      Status;
 | |
| 
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   //
 | |
|   // Detemine the internal syntax type
 | |
|   //
 | |
|   OnigSyntax = ONIG_SYNTAX_DEFAULT;
 | |
|   if (CompareGuid (SyntaxType, &gEfiRegexSyntaxTypePosixExtendedGuid)) {
 | |
|     OnigSyntax = ONIG_SYNTAX_POSIX_EXTENDED;
 | |
|   } else if (CompareGuid (SyntaxType, &gEfiRegexSyntaxTypePerlGuid)) {
 | |
|     OnigSyntax = ONIG_SYNTAX_PERL;
 | |
|   } else {
 | |
|     DEBUG ((DEBUG_ERROR, "Unsupported regex syntax - using default\n"));
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Compile pattern
 | |
|   //
 | |
|   Start = (OnigUChar*)Pattern;
 | |
|   OnigResult = onig_new (
 | |
|                  &OnigRegex,
 | |
|                  Start,
 | |
|                  Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start),
 | |
|                  ONIG_OPTION_DEFAULT,
 | |
|                  CHAR16_ENCODING,
 | |
|                  OnigSyntax,
 | |
|                  &ErrorInfo
 | |
|                  );
 | |
| 
 | |
|   if (OnigResult != ONIG_NORMAL) {
 | |
|     onig_error_code_to_str (ErrorMessage, OnigResult, &ErrorInfo);
 | |
|     DEBUG ((DEBUG_ERROR, "Regex compilation failed: %a\n", ErrorMessage));
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Try to match
 | |
|   //
 | |
|   Start = (OnigUChar*)String;
 | |
|   Region = onig_region_new ();
 | |
|   if (Region == NULL) {
 | |
|     onig_free (OnigRegex);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   OnigResult = onig_search (
 | |
|                  OnigRegex,
 | |
|                  Start,
 | |
|                  Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start),
 | |
|                  Start,
 | |
|                  Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start),
 | |
|                  Region,
 | |
|                  ONIG_OPTION_NONE
 | |
|                  );
 | |
| 
 | |
|   if (OnigResult >= 0) {
 | |
|     *Result = TRUE;
 | |
|   } else {
 | |
|     *Result = FALSE;
 | |
|     if (OnigResult != ONIG_MISMATCH) {
 | |
|       onig_error_code_to_str (ErrorMessage, OnigResult);
 | |
|       DEBUG ((DEBUG_ERROR, "Regex match failed: %a\n", ErrorMessage));
 | |
|       onig_region_free (Region, 1);
 | |
|       onig_free (OnigRegex);
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // If successful, copy out the region (capture) information
 | |
|   //
 | |
|   if (*Result && Captures != NULL) {
 | |
|     *CapturesCount = Region->num_regs;
 | |
|     *Captures = AllocateZeroPool (*CapturesCount * sizeof(**Captures));
 | |
|     if (*Captures != NULL) {
 | |
|       for (Index = 0; Index < *CapturesCount; ++Index) {
 | |
|         //
 | |
|         // Region beg/end values represent bytes, not characters
 | |
|         //
 | |
|         (*Captures)[Index].Length = (Region->end[Index] - Region->beg[Index]) / sizeof(CHAR16);
 | |
|         (*Captures)[Index].CapturePtr = AllocateCopyPool (
 | |
|                                           ((*Captures)[Index].Length) * sizeof (CHAR16),
 | |
|                                           (CHAR16*)((UINTN)String + Region->beg[Index])
 | |
|                                           );
 | |
|         if ((*Captures)[Index].CapturePtr == NULL) {
 | |
|           Status = EFI_OUT_OF_RESOURCES;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         for (Index = 0; Index < *CapturesCount; ++Index) {
 | |
|           if ((*Captures)[Index].CapturePtr != NULL) {
 | |
|             FreePool ((CHAR16*)(*Captures)[Index].CapturePtr);
 | |
|           }
 | |
|         }
 | |
|         FreePool (*Captures);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   onig_region_free (Region, 1);
 | |
|   onig_free (OnigRegex);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Returns information about the regular expression syntax types supported
 | |
|   by the implementation.
 | |
| 
 | |
|   @param This                      A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL
 | |
|                                    instance.
 | |
| 
 | |
|   @param  RegExSyntaxTypeListSize  On input, the size in bytes of RegExSyntaxTypeList.
 | |
|                                    On output with a return code of EFI_SUCCESS, the
 | |
|                                    size in bytes of the data returned in
 | |
|                                    RegExSyntaxTypeList. On output with a return code
 | |
|                                    of EFI_BUFFER_TOO_SMALL, the size of
 | |
|                                    RegExSyntaxTypeList required to obtain the list.
 | |
| 
 | |
|   @param   RegExSyntaxTypeList     A caller-allocated memory buffer filled by the
 | |
|                                    driver with one EFI_REGEX_SYNTAX_TYPE element
 | |
|                                    for each supported Regular expression syntax
 | |
|                                    type. The list must not change across multiple
 | |
|                                    calls to the same driver. The first syntax
 | |
|                                    type in the list is the default type for the
 | |
|                                    driver.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The regular expression syntax types list
 | |
|                                  was returned successfully.
 | |
|   @retval EFI_UNSUPPORTED        The service is not supported by this driver.
 | |
|   @retval EFI_DEVICE_ERROR       The list of syntax types could not be
 | |
|                                  retrieved due to a hardware or firmware error.
 | |
|   @retval EFI_BUFFER_TOO_SMALL   The buffer RegExSyntaxTypeList is too small
 | |
|                                  to hold the result.
 | |
|   @retval EFI_INVALID_PARAMETER  RegExSyntaxTypeListSize is NULL
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| RegularExpressionGetInfo (
 | |
|   IN     EFI_REGULAR_EXPRESSION_PROTOCOL *This,
 | |
|   IN OUT UINTN                           *RegExSyntaxTypeListSize,
 | |
|   OUT    EFI_REGEX_SYNTAX_TYPE           *RegExSyntaxTypeList
 | |
|   )
 | |
| {
 | |
|   UINTN SyntaxSize;
 | |
|   UINTN Index;
 | |
| 
 | |
|   if (This == NULL || RegExSyntaxTypeListSize == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (*RegExSyntaxTypeListSize != 0 && RegExSyntaxTypeList == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   SyntaxSize = ARRAY_SIZE (mSupportedSyntaxes) * sizeof(**mSupportedSyntaxes);
 | |
| 
 | |
|   if (*RegExSyntaxTypeListSize < SyntaxSize) {
 | |
|     *RegExSyntaxTypeListSize = SyntaxSize;
 | |
|     return EFI_BUFFER_TOO_SMALL;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < ARRAY_SIZE (mSupportedSyntaxes); ++Index) {
 | |
|     CopyMem (&RegExSyntaxTypeList[Index], mSupportedSyntaxes[Index], sizeof(**mSupportedSyntaxes));
 | |
|   }
 | |
|   *RegExSyntaxTypeListSize = SyntaxSize;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Checks if the input string matches to the regular expression pattern.
 | |
| 
 | |
|   @param This          A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL instance.
 | |
|                        Type EFI_REGULAR_EXPRESSION_PROTOCOL is defined in Section
 | |
|                        XYZ.
 | |
| 
 | |
|   @param String        A pointer to a NULL terminated string to match against the
 | |
|                        regular expression string specified by Pattern.
 | |
| 
 | |
|   @param Pattern       A pointer to a NULL terminated string that represents the
 | |
|                        regular expression.
 | |
| 
 | |
|   @param SyntaxType    A pointer to the EFI_REGEX_SYNTAX_TYPE that identifies the
 | |
|                        regular expression syntax type to use. May be NULL in which
 | |
|                        case the function will use its default regular expression
 | |
|                        syntax type.
 | |
| 
 | |
|   @param Result        On return, points to TRUE if String fully matches against
 | |
|                        the regular expression Pattern using the regular expression
 | |
|                        SyntaxType. Otherwise, points to FALSE.
 | |
| 
 | |
|   @param Captures      A Pointer to an array of EFI_REGEX_CAPTURE objects to receive
 | |
|                        the captured groups in the event of a match. The full
 | |
|                        sub-string match is put in Captures[0], and the results of N
 | |
|                        capturing groups are put in Captures[1:N]. If Captures is
 | |
|                        NULL, then this function doesn't allocate the memory for the
 | |
|                        array and does not build up the elements. It only returns the
 | |
|                        number of matching patterns in CapturesCount. If Captures is
 | |
|                        not NULL, this function returns a pointer to an array and
 | |
|                        builds up the elements in the array. CapturesCount is also
 | |
|                        updated to the number of matching patterns found. It is the
 | |
|                        caller's responsibility to free the memory pool in Captures
 | |
|                        and in each CapturePtr in the array elements.
 | |
| 
 | |
|   @param CapturesCount On output, CapturesCount is the number of matching patterns
 | |
|                        found in String. Zero means no matching patterns were found
 | |
|                        in the string.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The regular expression string matching
 | |
|                                  completed successfully.
 | |
|   @retval EFI_UNSUPPORTED        The regular expression syntax specified by
 | |
|                                  SyntaxType is not supported by this driver.
 | |
|   @retval EFI_DEVICE_ERROR       The regular expression string matching
 | |
|                                  failed due to a hardware or firmware error.
 | |
|   @retval EFI_INVALID_PARAMETER  String, Pattern, Result, or CapturesCountis
 | |
|                                  NULL.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| RegularExpressionMatch (
 | |
|   IN  EFI_REGULAR_EXPRESSION_PROTOCOL *This,
 | |
|   IN  CHAR16                          *String,
 | |
|   IN  CHAR16                          *Pattern,
 | |
|   IN  EFI_REGEX_SYNTAX_TYPE           *SyntaxType, OPTIONAL
 | |
|   OUT BOOLEAN                         *Result,
 | |
|   OUT EFI_REGEX_CAPTURE               **Captures, OPTIONAL
 | |
|   OUT UINTN                           *CapturesCount
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      Index;
 | |
|   BOOLEAN     Supported;
 | |
| 
 | |
|   if (This == NULL || String == NULL || Pattern == NULL || Result == NULL || CapturesCount == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Figure out which syntax to use
 | |
|   //
 | |
|   if (SyntaxType == NULL) {
 | |
|     SyntaxType = mSupportedSyntaxes[0];
 | |
|   } else {
 | |
|     Supported = FALSE;
 | |
|     for (Index = 0; Index < ARRAY_SIZE (mSupportedSyntaxes); ++Index) {
 | |
|       if (CompareGuid (SyntaxType, mSupportedSyntaxes[Index])) {
 | |
|         Supported = TRUE;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     if (!Supported) {
 | |
|       return EFI_UNSUPPORTED;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Status = OnigurumaMatch (String, Pattern, SyntaxType, Result, Captures, CapturesCount);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Entry point for RegularExpressionDxe.
 | |
| 
 | |
|   @param ImageHandle     Image handle this driver.
 | |
|   @param SystemTable     Pointer to SystemTable.
 | |
| 
 | |
|   @retval Status         Whether this function complete successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| RegularExpressionDxeEntry (
 | |
|   IN  EFI_HANDLE        ImageHandle,
 | |
|   IN  EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                   &ImageHandle,
 | |
|                   &gEfiRegularExpressionProtocolGuid,
 | |
|                   &mProtocolInstance,
 | |
|                   NULL
 | |
|                   );
 | |
| 
 | |
|   return Status;
 | |
| }
 |