Skip to content

Commit

Permalink
[gsupplicant] Make sure that BSS SSID string is a valid UTF-8
Browse files Browse the repository at this point in the history
  • Loading branch information
monich committed Mar 13, 2017
1 parent e06425e commit dc10bdf
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 8 deletions.
54 changes: 54 additions & 0 deletions include/gsupplicant_util.h
@@ -0,0 +1,54 @@
/*
* Copyright (C) 2017 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef GSUPPLICANT_UTIL_H
#define GSUPPLICANT_UTIL_H

#include <gsupplicant_types.h>

G_BEGIN_DECLS

char*
gsupplicant_utf8_from_bytes(
GBytes* bytes);

G_END_DECLS

#endif /* GSUPPLICANT_UTIL_H */

/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/
6 changes: 1 addition & 5 deletions src/gsupplicant_bss.c
Expand Up @@ -433,11 +433,7 @@ gsupplicant_bss_update_ssid(
}
g_free(priv->ssid_str);
if (ssid) {
gsize size = 0;
const void* data = g_bytes_get_data(ssid, &size);
priv->ssid_str = g_malloc(size + 1);
memcpy(priv->ssid_str, data, size);
priv->ssid_str[size] = 0;
priv->ssid_str = gsupplicant_utf8_from_bytes(ssid);
GDEBUG("[%s] " PROXY_PROPERTY_NAME_SSID ": %s \"%s\"",
self->path, gsupplicant_format_bytes(ssid, FALSE),
priv->ssid_str);
Expand Down
30 changes: 30 additions & 0 deletions src/gsupplicant_util.c
Expand Up @@ -439,6 +439,36 @@ gsupplicant_variant_data_as_bytes(
return NULL;
}

char*
gsupplicant_utf8_from_bytes(
GBytes* bytes)
{
if (bytes) {
gsize size = 0;
const char* ptr = g_bytes_get_data(bytes, &size);
if (size) {
GString* buf = g_string_sized_new(size);
while (size) {
const gchar* invalid = NULL;
if (g_utf8_validate(ptr, size, &invalid)) {
g_string_append_len(buf, ptr, size);
break;
} else {
gsize valid = invalid - ptr;
/* U+FFFD is REPLACEMENT CHARACTER */
g_string_append_len(buf, ptr, valid);
g_string_append(buf, "\357\277\275");
ptr = invalid + 1;
size -= valid + 1;
}
}
return g_string_free(buf, FALSE);
}
return g_strdup("");
}
return NULL;
}

/*
* Local Variables:
* mode: C
Expand Down
2 changes: 1 addition & 1 deletion src/gsupplicant_util_p.h
Expand Up @@ -33,7 +33,7 @@
#ifndef GSUPPLICANT_UTIL_PRIVATE_H
#define GSUPPLICANT_UTIL_PRIVATE_H

#include <gsupplicant_types.h>
#include <gsupplicant_util.h>

typedef struct gsupplicant_name_int_pair {
const char* name;
Expand Down
93 changes: 91 additions & 2 deletions test/test_util/test_util.c
Expand Up @@ -37,6 +37,8 @@
#include <gutil_log.h>
#include <glib/gstdio.h>

#define TEST_PREFIX "/util/"

#define BIT_FOO 0x01
#define BIT_BAR 0x02
#define BIT_EMPTY 0x04
Expand Down Expand Up @@ -435,13 +437,95 @@ test_util_dict_parse(
}

/*==========================================================================*
* Common
* utf8_from_bytes
*==========================================================================*/

#define TEST_PREFIX "/util/"
typedef struct test_util_utf8_data {
const char* name;
const void* in;
gsize in_size;
const guint32* ucs4;
glong ucs4_len;
} TestUTF8Data;

static const guint8 test_util_utf8_data_1_in[] = {
0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82
};
static const guint32 test_util_utf8_data_1_ucs4[] = {
0x0442, 0x0435, 0x0441, 0x0442
};
static const guint8 test_util_utf8_data_2_in[] = {
0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0x81
};
static const guint32 test_util_utf8_data_2_ucs4[] = {
0x0442, 0x0435, 0x0441, 0x0442, 0xfffd
};
static const guint8 test_util_utf8_data_3_in[] = {
0xf0, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82
};
static const guint32 test_util_utf8_data_3_ucs4[] = {
0xfffd, 0x0442, 0x0435, 0x0441, 0x0442
};
static const TestUTF8Data test_util_utf8_data[] = {
{
TEST_PREFIX "utf8_from_bytes1",
test_util_utf8_data_1_in, G_N_ELEMENTS(test_util_utf8_data_1_in),
test_util_utf8_data_1_ucs4, G_N_ELEMENTS(test_util_utf8_data_1_ucs4)
},{
TEST_PREFIX "utf8_from_bytes2",
test_util_utf8_data_2_in, G_N_ELEMENTS(test_util_utf8_data_2_in),
test_util_utf8_data_2_ucs4, G_N_ELEMENTS(test_util_utf8_data_2_ucs4)
},{
TEST_PREFIX "utf8_from_bytes3",
test_util_utf8_data_3_in, G_N_ELEMENTS(test_util_utf8_data_3_in),
test_util_utf8_data_3_ucs4, G_N_ELEMENTS(test_util_utf8_data_3_ucs4)
}
};

static
void
test_util_utf8_from_bytes(
void)
{
GBytes* nothing = g_bytes_new_static(NULL, 0);
char* empty = gsupplicant_utf8_from_bytes(nothing);
g_assert(!g_strcmp0(empty, ""));
g_assert(!gsupplicant_utf8_from_bytes(NULL));
g_bytes_unref(nothing);
g_free(empty);
}

static
void
test_util_utf8_from_bytes1(
gconstpointer data)
{
const TestUTF8Data* test = data;
GBytes* bytes = g_bytes_new_static(test->in, test->in_size);
char* utf8 = gsupplicant_utf8_from_bytes(bytes);
if (utf8) {
GError* error = NULL;
glong len = 0;
gunichar* ucs4 = g_utf8_to_ucs4(utf8, -1, NULL, &len, &error);
g_assert(!error);
g_assert(test->ucs4);
g_assert(test->ucs4_len == len);
g_assert(!memcmp(ucs4, test->ucs4, sizeof(guint32)*len));
g_free(utf8);
g_free(ucs4);
} else {
g_assert(!test->ucs4);
}
g_bytes_unref(bytes);
}

/*==========================================================================*
* Common
*==========================================================================*/

int main(int argc, char* argv[])
{
int i;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
g_type_init();
G_GNUC_END_IGNORE_DEPRECATIONS;
Expand All @@ -453,6 +537,11 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_PREFIX "cancel_later", test_util_cancel_later);
g_test_add_func(TEST_PREFIX "abs_path", test_util_abs_path);
g_test_add_func(TEST_PREFIX "dict_parse", test_util_dict_parse);
g_test_add_func(TEST_PREFIX "utf8_from_bytes", test_util_utf8_from_bytes);
for (i = 0; i < G_N_ELEMENTS(test_util_utf8_data); i++) {
const TestUTF8Data* test = test_util_utf8_data + i;
g_test_add_data_func(test->name, test, test_util_utf8_from_bytes1);
}
test_init(&test_opt, argc, argv);
return g_test_run();
}
Expand Down

0 comments on commit dc10bdf

Please sign in to comment.