Bug 860727 - Implement UTF-8 code unit counting without setlocale().
Counting the code points in a UTF-8 string is simple enough that that it is
not worthwhile to use the locale-dependent parts of the C standard library
for the task.
MozReview-Commit-ID: 6Tzd5NHub3B
--- a/media/mtransport/third_party/nICEr/src/stun/stun_codec.c
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_codec.c
@@ -47,17 +47,16 @@ static char *RCSSTRING __UNUSED__="$Id:
#include <assert.h>
#include <stddef.h>
#include "nr_api.h"
#include "stun.h"
#include "byteorder.h"
#include "r_crc32.h"
#include "nr_crypto.h"
-#include "mbslen.h"
#define NR_STUN_IPV4_FAMILY 0x01
#define NR_STUN_IPV6_FAMILY 0x02
#define SKIP_ATTRIBUTE_DECODE -1
static int nr_stun_find_attr_info(UINT2 type, nr_stun_attr_info **info);
@@ -207,33 +206,56 @@ nr_stun_decode(int length, UCHAR *buf, i
}
memcpy(data, &buf[*offset], length);
*offset += length;
return 0;
}
+/**
+ * The argument must be a non-null pointer to a zero-terminated string.
+ *
+ * If the argument is valid UTF-8, returns the number of code points in the
+ * string excluding the zero-terminator.
+ *
+ * If the argument is invalid UTF-8, returns a lower bound for the number of
+ * code points in the string. (If UTF-8 error handling was performed on the
+ * string, new REPLACEMENT CHARACTER code points could be introduced in
+ * a way that would increase the total number of code points compared to
+ * what this function counts.)
+ */
+size_t
+nr_count_utf8_code_points_without_validation(const char *s) {
+ size_t nchars = 0;
+ char c;
+ while ((c = *s)) {
+ if ((c & 0xC0) != 0x80) {
+ ++nchars;
+ }
+ ++s;
+ }
+ return nchars;
+}
+
int
nr_stun_attr_string_illegal(nr_stun_attr_info *attr_info, int len, void *data, int max_bytes, int max_chars)
{
int _status;
char *s = data;
size_t nchars;
if (len > max_bytes) {
r_log(NR_LOG_STUN, LOG_WARNING, "%s is too large: %d bytes", attr_info->name, len);
ABORT(R_FAILED);
}
if (max_chars >= 0) {
- if (mbslen(s, &nchars)) {
- /* who knows what to do, just assume everything is working ok */
- }
- else if (nchars > max_chars) {
+ nchars = nr_count_utf8_code_points_without_validation(s);
+ if (nchars > max_chars) {
r_log(NR_LOG_STUN, LOG_WARNING, "%s is too large: %zd characters", attr_info->name, nchars);
ABORT(R_FAILED);
}
}
_status = 0;
abort:
return _status;
--- a/media/mtransport/third_party/nICEr/src/stun/stun_codec.h
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_codec.h
@@ -65,14 +65,14 @@ extern nr_stun_attr_codec nr_stun_attr_c
extern nr_stun_attr_codec nr_stun_attr_codec_noop;
extern nr_stun_attr_codec nr_stun_attr_codec_quoted_string;
extern nr_stun_attr_codec nr_stun_attr_codec_string;
extern nr_stun_attr_codec nr_stun_attr_codec_unknown_attributes;
extern nr_stun_attr_codec nr_stun_attr_codec_xor_mapped_address;
extern nr_stun_attr_codec nr_stun_attr_codec_xor_peer_address;
extern nr_stun_attr_codec nr_stun_attr_codec_old_xor_mapped_address;
-
+size_t nr_count_utf8_code_points_without_validation(const char *s);
int nr_stun_encode_message(nr_stun_message *msg);
int nr_stun_decode_message(nr_stun_message *msg, int (*get_password)(void *arg, nr_stun_message *msg, Data **password), void *arg);
#endif