int wind_ucs4utf8_copy(const uint32_t *in, size_t in_len, char **out, size_t *out_len) { size_t size; int ret; ret = wind_ucs4utf8_length(in, in_len, &size); if (ret) return ret; size += 1; *out = malloc(size); if (*out == NULL) return ENOMEM; ret = wind_ucs4utf8(in, in_len, *out, &size); if (ret) { free(*out); *out = NULL; return ret; } if (out_len) *out_len = size; return 0; }
int hx509_name_get_component(hx509_name name, int rdn, const heim_oid *type, unsigned *count, char **str) { Name *n = &name->der_name; size_t len, ulen; uint32_t *ds; unsigned i; int ret; if (str) *str = NULL; if (rdn >= n->u.rdnSequence.len) return ERANGE; for (i = *count; i < n->u.rdnSequence.val[rdn].len; i++) { if (der_heim_oid_cmp(&n->u.rdnSequence.val[rdn].val[i].type, type) == 0) { *count = i + 1; if (str == NULL) return HX509_NAME_MALFORMED; ret = dsstringprep(&n->u.rdnSequence.val[rdn].val[i].value, &ds, &len); if (ret) return ret; ret = wind_ucs4utf8_length(ds, len, &ulen); if (ret) { free(ds); return ret; } ulen += 1; *str = malloc(ulen); if (str == NULL) { free(ds); return ENOMEM; } ret = wind_ucs4utf8(ds, len, *str, &ulen); free(ds); if (ret) { free(*str); *str = NULL; return ret; } return 0; } } if (str == NULL) return 0; return HX509_NAME_MALFORMED; }
int wind_ucs4utf8_length(const uint32_t *in, size_t in_len, size_t *out_len) { return wind_ucs4utf8(in, in_len, NULL, out_len); }
int _hx509_Name_to_string(const Name *n, char **str) { size_t total_len = 0; size_t i, j, m; int ret; *str = strdup(""); if (*str == NULL) return ENOMEM; for (m = n->u.rdnSequence.len; m > 0; m--) { size_t len; i = m - 1; for (j = 0; j < n->u.rdnSequence.val[i].len; j++) { DirectoryString *ds = &n->u.rdnSequence.val[i].val[j].value; char *oidname; char *ss; oidname = oidtostring(&n->u.rdnSequence.val[i].val[j].type); switch(ds->element) { case choice_DirectoryString_ia5String: ss = ds->u.ia5String.data; len = ds->u.ia5String.length; break; case choice_DirectoryString_printableString: ss = ds->u.printableString.data; len = ds->u.printableString.length; break; case choice_DirectoryString_utf8String: ss = ds->u.utf8String; len = strlen(ss); break; case choice_DirectoryString_bmpString: { const uint16_t *bmp = ds->u.bmpString.data; size_t bmplen = ds->u.bmpString.length; size_t k; ret = wind_ucs2utf8_length(bmp, bmplen, &k); if (ret) { free(oidname); free(*str); *str = NULL; return ret; } ss = malloc(k + 1); if (ss == NULL) _hx509_abort("allocation failure"); /* XXX */ ret = wind_ucs2utf8(bmp, bmplen, ss, NULL); if (ret) { free(oidname); free(ss); free(*str); *str = NULL; return ret; } ss[k] = '\0'; len = k; break; } case choice_DirectoryString_teletexString: ss = ds->u.teletexString; len = strlen(ss); break; case choice_DirectoryString_universalString: { const uint32_t *uni = ds->u.universalString.data; size_t unilen = ds->u.universalString.length; size_t k; ret = wind_ucs4utf8_length(uni, unilen, &k); if (ret) { free(oidname); free(*str); *str = NULL; return ret; } ss = malloc(k + 1); if (ss == NULL) _hx509_abort("allocation failure"); /* XXX */ ret = wind_ucs4utf8(uni, unilen, ss, NULL); if (ret) { free(ss); free(oidname); free(*str); *str = NULL; return ret; } ss[k] = '\0'; len = k; break; } default: _hx509_abort("unknown directory type: %d", ds->element); exit(1); } append_string(str, &total_len, oidname, strlen(oidname), 0); free(oidname); append_string(str, &total_len, "=", 1, 0); append_string(str, &total_len, ss, len, 1); if (ds->element == choice_DirectoryString_bmpString || ds->element == choice_DirectoryString_universalString) { free(ss); } if (j + 1 < n->u.rdnSequence.val[i].len) append_string(str, &total_len, "+", 1, 0); } if (i > 0) append_string(str, &total_len, ",", 1, 0); } return 0; }
int main(void) { unsigned failures = 0; unsigned i; const char **s; int ret; size_t len, len2; uint32_t u[MAX_LENGTH]; char str[MAX_LENGTH * 4]; for (s = failing_testcases; *s != NULL; ++s) { len = MAX_LENGTH; ret = wind_utf8ucs4(*s, u, &len); if (ret == 0) { printf("utf8 decode of \"%s\" should have failed\n", *s); ++failures; } } for (i = 0; i < sizeof(testcases)/sizeof(testcases[0]); ++i) { const struct testcase *t = &testcases[i]; ret = wind_utf8ucs4_length(t->utf8_str, &len); if (ret) { printf("utf8ucs4 length of \"%s\" should have succeeded\n", t->utf8_str); ++failures; continue; } if (len != t->len) { printf("utf8ucs4_length of \"%s\" has wrong length: " "expected: %u, actual: %u\n", t->utf8_str, (unsigned int)t->len, (unsigned int)len); ++failures; continue; } len = MAX_LENGTH; ret = wind_utf8ucs4(t->utf8_str, u, &len); if (ret) { printf("utf8 decode of \"%s\" should have succeeded\n", t->utf8_str); ++failures; continue; } if (len != t->len) { printf("utf8 decode of \"%s\" has wrong length: " "expected: %u, actual: %u\n", t->utf8_str, (unsigned int)t->len, (unsigned int)len); ++failures; continue; } if (memcmp(t->u, u, len * sizeof(uint32_t)) != 0) { printf("utf8 decode of \"%s\" has wrong data\n", t->utf8_str); ++failures; continue; } if (t->invalid_ucs2 == 0) { len2 = sizeof(str); ret = wind_ucs4utf8(u, len, str, &len2); if (ret) { printf("ucs4 decode of \"%s\" should have succeeded\n", t->utf8_str); ++failures; continue; } } } return failures != 0; }