Blame lib/str-iconv.c

Packit Service 4684c1
/*
Packit Service 4684c1
 * Copyright (C) 2010-2016 Free Software Foundation, Inc.
Packit Service 4684c1
 * Copyright (C) 2015-2016 Red Hat, Inc.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Author: Nikos Mavrogiannopoulos
Packit Service 4684c1
 *
Packit Service 4684c1
 * This file is part of GnuTLS.
Packit Service 4684c1
 *
Packit Service 4684c1
 * The GnuTLS is free software; you can redistribute it and/or
Packit Service 4684c1
 * modify it under the terms of the GNU Lesser General Public License
Packit Service 4684c1
 * as published by the Free Software Foundation; either version 2.1 of
Packit Service 4684c1
 * the License, or (at your option) any later version.
Packit Service 4684c1
 *
Packit Service 4684c1
 * This library is distributed in the hope that it will be useful, but
Packit Service 4684c1
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 4684c1
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 4684c1
 * Lesser General Public License for more details.
Packit Service 4684c1
 *
Packit Service 4684c1
 * You should have received a copy of the GNU Lesser General Public License
Packit Service 4684c1
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
Packit Service 4684c1
 *
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
#include <config.h>
Packit Service 4684c1
#include <system.h>
Packit Service 4684c1
#include "gnutls_int.h"
Packit Service 4684c1
#include "errors.h"
Packit Service 4684c1
Packit Service 4684c1
#include <sys/socket.h>
Packit Service 4684c1
#include <errno.h>
Packit Service 4684c1
#include <sys/stat.h>
Packit Service 4684c1
#include <sys/types.h>
Packit Service 4684c1
#include <unistr.h>
Packit Service 4684c1
#include <uninorm.h>
Packit Service 4684c1
#include "num.h"
Packit Service 4684c1
Packit Service 4684c1
static void change_u16_endianness(uint8_t *dst, const uint8_t *src, unsigned size, unsigned be)
Packit Service 4684c1
{
Packit Service 4684c1
	unsigned convert = 0;
Packit Service 4684c1
	unsigned i;
Packit Service 4684c1
	uint8_t tmp;
Packit Service 4684c1
Packit Service 4684c1
#ifdef WORDS_BIGENDIAN
Packit Service 4684c1
	if (!be)
Packit Service 4684c1
		convert = 1;
Packit Service 4684c1
#else
Packit Service 4684c1
	if (be)
Packit Service 4684c1
		convert = 1;
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
	/* convert to LE */
Packit Service 4684c1
	if (convert) {
Packit Service 4684c1
		for (i = 0; i < size; i += 2) {
Packit Service 4684c1
			tmp = src[i];
Packit Service 4684c1
			dst[i] = src[1 + i];
Packit Service 4684c1
			dst[1 + i] = tmp;
Packit Service 4684c1
		}
Packit Service 4684c1
	} else {
Packit Service 4684c1
		if (dst != src)
Packit Service 4684c1
			memcpy(dst, src, size);
Packit Service 4684c1
	}
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
int _gnutls_ucs2_to_utf8(const void *data, size_t size,
Packit Service 4684c1
			 gnutls_datum_t * output, unsigned be)
Packit Service 4684c1
{
Packit Service 4684c1
	int ret;
Packit Service 4684c1
	size_t dstlen;
Packit Service 4684c1
	void *src;
Packit Service 4684c1
	uint8_t *tmp_dst = NULL;
Packit Service 4684c1
	uint8_t *dst = NULL;
Packit Service 4684c1
Packit Service 4684c1
	if (size > 2 && ((uint8_t *) data)[size-1] == 0 && ((uint8_t *) data)[size-2] == 0) {
Packit Service 4684c1
		size -= 2;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	if (size == 0)
Packit Service 4684c1
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit Service 4684c1
Packit Service 4684c1
	src = gnutls_malloc(size+2);
Packit Service 4684c1
	if (src == NULL)
Packit Service 4684c1
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
Packit Service 4684c1
Packit Service 4684c1
	/* convert to LE if needed */
Packit Service 4684c1
	change_u16_endianness(src, data, size, be);
Packit Service 4684c1
Packit Service 4684c1
	dstlen = 0;
Packit Service 4684c1
	tmp_dst = u16_to_u8((uint16_t*)src, size/2, NULL, &dstlen);
Packit Service 4684c1
	if (tmp_dst == NULL) {
Packit Service 4684c1
		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
Packit Service 4684c1
		goto fail;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	dst = gnutls_malloc(dstlen+1);
Packit Service 4684c1
	if (dst == NULL) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		ret = GNUTLS_E_MEMORY_ERROR;
Packit Service 4684c1
		goto fail;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	memcpy(dst, tmp_dst, dstlen);
Packit Service 4684c1
	dst[dstlen] = 0;
Packit Service 4684c1
Packit Service 4684c1
	output->data = (void *) dst;
Packit Service 4684c1
	output->size = dstlen;
Packit Service 4684c1
Packit Service 4684c1
	ret = 0;
Packit Service 4684c1
	goto cleanup;
Packit Service 4684c1
Packit Service 4684c1
 fail:
Packit Service 4684c1
	gnutls_free(dst);
Packit Service 4684c1
Packit Service 4684c1
 cleanup:
Packit Service 4684c1
	gnutls_free(src);
Packit Service 4684c1
	free(tmp_dst);
Packit Service 4684c1
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
int _gnutls_utf8_to_ucs2(const void *data, size_t size,
Packit Service 4684c1
			 gnutls_datum_t * output, unsigned be)
Packit Service 4684c1
{
Packit Service 4684c1
	int ret;
Packit Service 4684c1
	size_t dstlen, nrm_size = 0, tmp_size = 0;
Packit Service 4684c1
	uint16_t *tmp_dst = NULL;
Packit Service 4684c1
	uint16_t *nrm_dst = NULL;
Packit Service 4684c1
	uint8_t *dst = NULL;
Packit Service 4684c1
Packit Service 4684c1
	if (size == 0)
Packit Service 4684c1
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit Service 4684c1
Packit Service 4684c1
	tmp_dst = u8_to_u16(data, size, NULL, &tmp_size);
Packit Service 4684c1
	if (tmp_dst == NULL)
Packit Service 4684c1
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
Packit Service 4684c1
Packit Service 4684c1
	nrm_dst = u16_normalize(UNINORM_NFC, tmp_dst, tmp_size, NULL, &nrm_size);
Packit Service 4684c1
	if (nrm_dst == NULL) {
Packit Service 4684c1
		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
Packit Service 4684c1
		goto fail;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	dstlen = nrm_size * 2; /* convert to bytes */
Packit Service 4684c1
Packit Service 4684c1
	dst = gnutls_malloc(dstlen+2);
Packit Service 4684c1
	if (dst == NULL) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		ret = GNUTLS_E_MEMORY_ERROR;
Packit Service 4684c1
		goto fail;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	/* convert to BE */
Packit Service 4684c1
	change_u16_endianness(dst, (uint8_t*)tmp_dst, dstlen, be);
Packit Service 4684c1
	dst[dstlen] = 0;
Packit Service 4684c1
	dst[dstlen+1] = 0;
Packit Service 4684c1
Packit Service 4684c1
	output->data = (void *) dst;
Packit Service 4684c1
	output->size = dstlen;
Packit Service 4684c1
Packit Service 4684c1
	ret = 0;
Packit Service 4684c1
	goto cleanup;
Packit Service 4684c1
Packit Service 4684c1
 fail:
Packit Service 4684c1
	gnutls_free(dst);
Packit Service 4684c1
Packit Service 4684c1
 cleanup:
Packit Service 4684c1
	free(tmp_dst);
Packit Service 4684c1
	free(nrm_dst);
Packit Service 4684c1
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1