/* * When provided with a Tpm2Command that represents a call to the * GetCapability command this function will extract the 'property' field. * On error 0 is returned. */ UINT32 tpm2_command_get_prop (Tpm2Command *command) { if (command == NULL) { g_warning ("tpm2_command_get_prop passed NULL parameter"); return 0; } if (tpm2_command_get_code (command) != TPM_CC_GetCapability) { g_warning ("tpm2_command_get_cap provided a Tpm2Command buffer " "containing the wrong command code."); return 0; } return (UINT32)be32toh (PROPERTY_GET (tpm2_command_get_buffer (command))); }
uint8_t utf8isnormalized(const char* input, size_t inputSize, size_t flags, size_t* offset) { const char* src = input; size_t src_size = inputSize; uint8_t last_canonical_class = CCC_NOT_REORDERED; size_t found_offset = 0; uint8_t result = UTF8_NORMALIZATION_RESULT_YES; unicode_t decoded; uint8_t canonical_class; uint8_t quick_check; const size_t* property_index; const uint8_t* property_data; /* Validate input and flags */ if (input == NULL || inputSize == 0 || (flags & (UTF8_NORMALIZE_DECOMPOSE | UTF8_NORMALIZE_COMPOSE)) == 0) { goto end; } /* Get properties */ if ((flags & UTF8_NORMALIZE_COMPOSE) != 0) { if ((flags & UTF8_NORMALIZE_COMPATIBILITY) != 0) { property_index = QuickCheckNFKCIndexPtr; property_data = QuickCheckNFKCDataPtr; } else { property_index = QuickCheckNFCIndexPtr; property_data = QuickCheckNFCDataPtr; } } else { if ((flags & UTF8_NORMALIZE_COMPATIBILITY) != 0) { property_index = QuickCheckNFKDIndexPtr; property_data = QuickCheckNFKDDataPtr; } else { property_index = QuickCheckNFDIndexPtr; property_data = QuickCheckNFDDataPtr; } } /* Process input */ while (src_size > 0) { /* Read codepoint at cursor */ uint8_t read = codepoint_read(src, src_size, &decoded); if (read == 0) { break; } /* Get canonical combining class and quick check value */ canonical_class = PROPERTY_GET_CCC(decoded); quick_check = PROPERTY_GET(property_index, property_data, decoded); /* Compare CCC to previous CCC */ if (last_canonical_class > canonical_class && canonical_class > CCC_NOT_REORDERED) { result = UTF8_NORMALIZATION_RESULT_NO; break; } /* Compare quick check value */ if (quick_check == QuickCheckResult_No) { result = UTF8_NORMALIZATION_RESULT_NO; break; } else if ( quick_check == QuickCheckResult_Maybe) { result = UTF8_NORMALIZATION_RESULT_MAYBE; } /* Append to offset */ if (result != UTF8_NORMALIZATION_RESULT_MAYBE) { found_offset += read; } last_canonical_class = canonical_class; src += read; src_size -= read; } end: if (offset != 0) { *offset = found_offset; } return result; }
size_t utf8normalize(const char* input, size_t inputSize, char* target, size_t targetSize, size_t flags, int32_t* errors) { char* dst = target; size_t dst_size = targetSize; StreamState stream[4]; DecomposeState decompose_state; ComposeState compose_state; uint8_t compatibility = (flags & UTF8_NORMALIZE_COMPATIBILITY) != 0; StreamState* stream_output; uint8_t finished = 0; size_t bytes_written = 0; /* Decomposition uses the following process: input --> stream[0] --> (decompose) --> stream[1] --> (accumulate) --> stream[2] --> output The accumulation step is necessary in order to prevent buffer overflow attacks. Composition adds another stream buffer: input --> stream[0] --> (decompose) --> stream[1] --> (accumulate) --> stream[2] --> (compose) --> stream[3] --> output Although four streaming buffers may seem excessive, they are necessary for preventing allocations on the heap. */ /* Check for valid flags */ if ((flags & (UTF8_NORMALIZE_DECOMPOSE | UTF8_NORMALIZE_COMPOSE)) == 0) { UTF8_SET_ERROR(INVALID_FLAG); return bytes_written; } /* Validate parameters */ UTF8_VALIDATE_PARAMETERS_CHAR(char, bytes_written); /* Initialize decomposition */ memset(stream, 0, sizeof(stream)); if (!stream_initialize(&stream[0], input, inputSize) || !decompose_initialize(&decompose_state, &stream[0], &stream[1], compatibility)) { UTF8_SET_ERROR(INVALID_DATA); return bytes_written; } stream_output = &stream[2]; if ((flags & UTF8_NORMALIZE_COMPOSE) != 0) { /* Initialize composition */ if (!compose_initialize(&compose_state, &stream[2], &stream[3], compatibility)) { UTF8_SET_ERROR(INVALID_DATA); return bytes_written; } stream_output = &stream[3]; } do { uint8_t write = 0; /* Accumulate decomposed input in next stream */ if (stream[1].current > 0) { unicode_t* src_codepoint = stream[1].codepoint; unicode_t* dst_codepoint = stream[2].codepoint + stream[2].filled; uint8_t* src_qc = stream[1].quick_check; uint8_t* dst_qc = stream[2].quick_check + stream[2].filled; uint8_t* src_ccc = stream[1].canonical_combining_class; uint8_t* dst_ccc = stream[2].canonical_combining_class + stream[2].filled; if ((flags & UTF8_NORMALIZE_COMPOSE) != 0) { uint8_t i; /* Update stream properties to use composition values */ for (i = 0; i < stream[1].current; ++i) { *dst_qc++ = PROPERTY_GET(compose_state.qc_index, compose_state.qc_data, *src_codepoint); *dst_ccc++ = *src_ccc++; *dst_codepoint++ = *src_codepoint++; } } else { /* Copy directly */ memcpy(dst_codepoint, src_codepoint, stream[1].current * sizeof(unicode_t)); memcpy(dst_qc, src_qc, stream[1].current * sizeof(uint8_t)); memcpy(dst_ccc, src_ccc, stream[1].current * sizeof(uint8_t)); } stream[2].current += stream[1].current; stream[2].filled += stream[1].current; } /* Decompose input sequence into next stream */ finished = !decompose_execute(&decompose_state); if (!finished) { /* Output current stream it it could overflow accumulation buffer */ write = (stream[1].current + stream[2].filled) >= STREAM_SAFE_MAX; } /* Reorder potentially unordered decomposed stream */ if (!stream[1].stable) { stream_reorder(&stream[1]); } /* Write stream to output when overflowing or when accumulation buffer is empty*/ if (write || finished) { uint8_t i; /* Compose accumulation buffer */ if ((flags & UTF8_NORMALIZE_COMPOSE) != 0 && !compose_execute(&compose_state)) { break; } /* Write to output buffer */ for (i = 0; i < stream_output->current; ++i) { uint8_t encoded_size = codepoint_write(stream_output->codepoint[i], &dst, &dst_size); if (encoded_size == 0) { UTF8_SET_ERROR(NOT_ENOUGH_SPACE); return bytes_written; } bytes_written += encoded_size; } /* Reset accumulation buffer */ stream[2].current = 0; stream[2].filled = 0; } } while (!finished); UTF8_SET_ERROR(NONE); return bytes_written; }