check for the minimal encoding length
diff --git a/skeletons/UTF8String.c b/skeletons/UTF8String.c
index 1c94645..934a424 100644
--- a/skeletons/UTF8String.c
+++ b/skeletons/UTF8String.c
@@ -47,20 +47,56 @@
4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 6, 6, -1, -1 }
};
+static int32_t UTF8String_mv[7] = { 0, 0,
+ 0x00000080,
+ 0x00000800,
+ 0x00010000,
+ 0x00200000,
+ 0x04000000
+};
+
+/* Internal aliases for return codes */
+#define U8E_TRUNC -1 /* UTF-8 sequence truncated */
+#define U8E_ILLSTART -2 /* Illegal UTF-8 sequence start */
+#define U8E_NOTCONT -3 /* Continuation expectation failed */
+#define U8E_NOTMIN -4 /* Not minimal length encoding */
+#define U8E_EINVAL -5 /* Invalid arguments */
int
UTF8String_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_consume_bytes_f *app_errlog, void *app_key) {
- ssize_t len;
- len = UTF8String_length((const UTF8String_t *)sptr, td->name,
- app_errlog, app_key);
- if(len > 0) len = 0;
- return len;
+ ssize_t len = UTF8String_length((const UTF8String_t *)sptr);
+ switch(len) {
+ case U8E_EINVAL:
+ _ASN_ERRLOG(app_errlog, app_key,
+ "%s: value not given", td->name);
+ break;
+ case U8E_TRUNC:
+ _ASN_ERRLOG(app_errlog, app_key,
+ "%s: truncated UTF-8 sequence (%s:%d)",
+ td->name, __FILE__, __LINE__);
+ break;
+ case U8E_ILLSTART:
+ _ASN_ERRLOG(app_errlog, app_key,
+ "%s: UTF-8 illegal start of encoding (%s:%d)",
+ td->name, __FILE__, __LINE__);
+ break;
+ case U8E_NOTCONT:
+ _ASN_ERRLOG(app_errlog, app_key,
+ "%s: UTF-8 not continuation (%s:%d)",
+ td->name, __FILE__, __LINE__);
+ break;
+ case U8E_NOTMIN:
+ _ASN_ERRLOG(app_errlog, app_key,
+ "%s: UTF-8 not minimal sequence (%s:%d)",
+ td->name, __FILE__, __LINE__);
+ break;
+ }
+ return (len < 0) ? -1 : 0;
}
ssize_t
-UTF8String_length(const UTF8String_t *st, const char *opt_type_name,
- asn_app_consume_bytes_f *app_errlog, void *app_key) {
+UTF8String_length(const UTF8String_t *st) {
if(st && st->buf) {
size_t length;
@@ -69,35 +105,41 @@
for(length = 0; buf < end; length++) {
int ch = *buf;
- int want = UTF8String_ht[0][ch >> 4];
+ uint8_t *cend;
+ int32_t value;
+ int want;
+
+ /* Compute the sequence length */
+ want = UTF8String_ht[0][ch >> 4];
switch(want) {
- case -1: /* Second half of the table, long sequence */
+ case -1:
+ /* Second half of the table, long sequence */
want = UTF8String_ht[1][ch & 0x0F];
- if(want != -1)
- break; /* Fine value */
- case 0: /* 10xxxxxx should not appear here */
- _ASN_ERRLOG(app_errlog, app_key,
- "%s: UTF-8 expectation failed "
- "at byte %d (%s:%d)",
- opt_type_name,
- (buf - st->buf) + 1,
- __FILE__, __LINE__);
- return -1;
+ if(want != -1) break;
+ /* Fall through */
+ case 0:
+ return U8E_ILLSTART;
}
- if(buf + want > end) {
- _ASN_ERRLOG(app_errlog, app_key,
- "%s: truncated UTF-8 sequence (%s:%d)",
- opt_type_name, __FILE__, __LINE__);
- return -1;
+
+ /* assert(want >= 1 && want <= 6) */
+
+ /* Check character sequence length */
+ if(buf + want > end) return U8E_TRUNC;
+
+ value = ch & (0xff >> (want + 1));
+ cend = buf + want;
+ for(buf++; buf < cend; buf++) {
+ ch = *buf;
+ if(ch < 0x80 || ch > 0xbf) return U8E_NOTCONT;
+ value = (value << 6) | (ch & 0x3F);
}
- buf += want;
+ if(value < UTF8String_mv[want])
+ return U8E_NOTMIN;
}
return length;
} else {
- _ASN_ERRLOG(app_errlog, app_key,
- "%s: value not given", opt_type_name);
- return -1;
+ return U8E_EINVAL;
}
}
diff --git a/skeletons/UTF8String.h b/skeletons/UTF8String.h
index a1149e4..4580159 100644
--- a/skeletons/UTF8String.h
+++ b/skeletons/UTF8String.h
@@ -14,8 +14,15 @@
asn_struct_print_f UTF8String_print;
asn_constr_check_f UTF8String_constraint;
-/* Returns length of UTF-8 string in characters or -1 if error. */
-ssize_t UTF8String_length(const UTF8String_t *st, const char *opt_type_name,
- asn_app_consume_bytes_f *app_errlog, void *app_key);
+/*
+ * Returns length of the given UTF-8 string in characters,
+ * or a negative error code:
+ * -1: UTF-8 sequence truncated
+ * -2: Illegal UTF-8 sequence start
+ * -3: Continuation expectation failed
+ * -4: Not minimal length encoding
+ * -5: Invalid arguments
+ */
+ssize_t UTF8String_length(const UTF8String_t *st);
#endif /* _UTF8String_H_ */