void *
UnicodeGetAllocBytesInternal(ConstUnicode ustr,       // IN
                             StringEncoding encoding, // IN
                             ssize_t lengthInBytes,   // IN
                             size_t *retLength)       // OUT: optional
{
   const char *utf8Str = ustr;
   char *result = NULL;

   ASSERT(ustr != NULL);

   encoding = Unicode_ResolveEncoding(encoding);

   if (lengthInBytes == -1) {
      lengthInBytes = Unicode_LengthInBytes(ustr, STRING_ENCODING_UTF8);
   }

   switch (encoding) {
   case STRING_ENCODING_US_ASCII:
      if (!UnicodeSanityCheck(utf8Str, lengthInBytes, encoding)) {
	 break;
      }
      // fall through
   case STRING_ENCODING_UTF8:
      result = Util_SafeMalloc(lengthInBytes + 1);
      memcpy(result, utf8Str, lengthInBytes + 1);
      if (retLength != NULL) {
	 *retLength = lengthInBytes;
      }
      break;

   case STRING_ENCODING_UTF16_LE:
      if (!CodeSet_Utf8ToUtf16le(utf8Str, lengthInBytes, &result, retLength)) {
	 // input should be valid UTF-8, no conversion error possible
	 ASSERT_MEM_ALLOC(FALSE);
      }
      break;

   default:
      if (!CodeSet_GenericToGeneric("UTF-8", utf8Str, lengthInBytes,
				    Unicode_EncodingEnumToName(encoding),
				    CSGTG_NORMAL,
				    &result, retLength)) {
	 // XXX can't distinguish error cause
	 ASSERT(result == NULL);
      }
   }

   return result;
}
Exemple #2
0
char *
Unicode_EscapeBuffer(const void *buffer,      // IN
                     ssize_t lengthInBytes,   // IN
                     StringEncoding encoding) // IN
{
   encoding = Unicode_ResolveEncoding(encoding);

   if (lengthInBytes == -1) {
      lengthInBytes = Unicode_LengthInBytes(buffer, encoding);
   }

   /*
    * The buffer could have NULs or 8-bit values inside.  Escape it.
    */
   return Escape_DoString("\\x",
                          NonPrintableBytesToEscape,
                          buffer,
                          lengthInBytes,
                          NULL);
}
Exemple #3
0
Unicode
Unicode_AllocWithLength(const void *buffer,       // IN:
                        ssize_t lengthInBytes,    // IN:
                        StringEncoding encoding)  // IN:
{
   Unicode result;

   ASSERT(lengthInBytes >= 0 || lengthInBytes == -1);

   if (buffer == NULL) {
      ASSERT(lengthInBytes <= 0);
      return NULL;
   }

   encoding = Unicode_ResolveEncoding(encoding);

   if (lengthInBytes == -1) {
      lengthInBytes = Unicode_LengthInBytes(buffer, encoding);
   }

   result = UnicodeAllocInternal(buffer, lengthInBytes, encoding, FALSE);

   if (result == NULL) {
      char *escapedBuffer = Unicode_EscapeBuffer(buffer, lengthInBytes,
                                                 encoding);

      /*
       * Log and panic on failure.
       */

      Log("%s: Couldn't convert invalid buffer [%s] from %s to Unicode.\n",
          __FUNCTION__,
          escapedBuffer ? escapedBuffer : "(couldn't escape bytes)",
          Unicode_EncodingEnumToName(encoding));
      free(escapedBuffer);
      PANIC();
   }

   return result;
}
Bool
Unicode_IsBufferValid(const void *buffer,      // IN
                      ssize_t lengthInBytes,   // IN
                      StringEncoding encoding) // IN
{
   if (buffer == NULL) {
      ASSERT(lengthInBytes <= 0);
      return TRUE;
   }

   encoding = Unicode_ResolveEncoding(encoding);

   if (encoding == STRING_ENCODING_US_ASCII) {
      return UnicodeSanityCheck(buffer, lengthInBytes, encoding);
   }

   if (lengthInBytes == -1) {
      lengthInBytes = Unicode_LengthInBytes(buffer, encoding);
   }

   return CodeSet_Validate(buffer, lengthInBytes,
			   Unicode_EncodingEnumToName(encoding));
}
LONG
Win32U_RegQueryValueEx(HKEY keyName,      // IN:
                       LPCSTR valueName,  // IN: can be NULL
                       LPDWORD reserved,  // IN: reserved
                       LPDWORD type,      // OUT: can be NULL
                       LPBYTE data,       // OUT: can be NULL
                       LPDWORD dataSize)  // IN/OUT: can be NULL if data is NULL
{
   LONG ret;
   utf16_t *valueNameW = Unicode_GetAllocUTF16(valueName);
   DWORD valueType;

   char *dataTemp = NULL;
   DWORD dataSizeTemp = 0;

   ASSERT(reserved == NULL);

   if (data) {
      ASSERT(dataSize != NULL);
      dataSizeTemp = *dataSize * 2;

      /*
       * We always allocate one extra word of space, so that we can write a
       * null character to the end of the data returned from the registry.
       * This protects us from crashing in the Win32UWriteBackRegData function
       * if the caller is attempting to get a value of type REG_SZ, and the
       * data is the registry is not properly null terminated.
       */

      dataTemp = Util_SafeMalloc(dataSizeTemp + sizeof L'\0');
   }

   ret = RegQueryValueExW(keyName, valueNameW, reserved, &valueType,
                          dataTemp, &dataSizeTemp);

   if (dataTemp && ERROR_SUCCESS == ret && REG_SZ == valueType) {
      /*
       * Append a null word to the returned data, in case the value is not
       * null terminated in the registry.
       */

      *((PWCHAR) (dataTemp + dataSizeTemp)) = L'\0';

      /*
       * Get the length of the string. The registry doesn't enforce any rules
       * on the consistency of the data written into a value of REG_SZ type,
       * so a poorly written application can end up writing bytes _after_ the
       * NULL character in the string (e.g., because of an off-by-one error).
       *
       * If we try to convert those extra bytes to utf8, the conversion will
       * typically fail and we get a Panic() (cf. bug 352057). Getting the
       * string length here prevents us from crashing in this (fairly common)
       * case, and cuts down on the number of support calls.
       */

      dataSizeTemp = Unicode_LengthInBytes(dataTemp, STRING_ENCODING_UTF16);
   }

   ret = Win32UWriteBackRegData(dataTemp, dataSizeTemp, data, dataSize,
                                valueType, ret);

   /* Write back the type information if asked for */
   if (type) {
      *type = valueType;
   }

   free(valueNameW);
   free(dataTemp);

   return ret;
}