Files
Marius Ciepluch 0116f9bea6 feat(real-world-vfc-slice): add labeled OpenSSL/Firefox/Chromium/curl pair corpus
Harvest 176 isolated vuln-vs-fix functions (109 CVEs, 352 training rows)
into benchmarks/pairs/vfc with provenance and a JSONL training manifest.
Score the slice as an honesty dashboard (ousast pairs --slice vfc);
keep the pair gate on the local fixtures only.
2026-09-04 16:45:38 +02:00

208 lines
5.6 KiB
C

/* Provenance: openssl/openssl ASN1_mbstring_ncopy (fixed).
* repo: openssl/openssl
* commit: 97f6b621f7af2c4c4e162c75045a6e12a8fdf8d9
* parent: cb005ceaaf1fb50722e0101762a3e266338c5bf9
* commit_url: https://github.com/openssl/openssl/commit/97f6b621f7af2c4c4e162c75045a6e12a8fdf8d9
* cve: CVE-2026-7383
* license: Apache-2.0
* function: ASN1_mbstring_ncopy
* relpath: crypto/asn1/a_mbstr.c
*/
int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
int inform, unsigned long mask_in,
long minsize, long maxsize)
{
int str_type;
int ret;
char free_out;
int outform, outlen = 0;
ASN1_STRING *dest;
unsigned char *p;
int nchar;
uint32_t mask = (uint32_t)mask_in;
int (*cpyfunc)(uint32_t, void *) = NULL;
if (len == -1) {
size_t len_s = strlen((const char *)in);
if (len_s >= INT_MAX) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG);
return -1;
}
len = (int)len_s;
}
if (!mask)
mask = DIRSTRING_TYPE;
if (len < 0) {
ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_INVALID_ARGUMENT);
return -1;
}
/* First do a string check and work out the number of characters */
switch (inform) {
case MBSTRING_BMP:
if (len & 1) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
return -1;
}
nchar = len >> 1;
break;
case MBSTRING_UNIV:
if (len & 3) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
return -1;
}
nchar = len >> 2;
break;
case MBSTRING_UTF8:
nchar = 0;
/* This counts the characters and does utf8 syntax checking */
ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
if (ret < 0) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UTF8STRING);
return -1;
}
break;
case MBSTRING_ASC:
nchar = len;
break;
default:
ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT);
return -1;
}
if ((minsize > 0) && (nchar < minsize)) {
ERR_raise_data(ERR_LIB_ASN1, ASN1_R_STRING_TOO_SHORT,
"minsize=%ld", minsize);
return -1;
}
if ((maxsize > 0) && (nchar > maxsize)) {
ERR_raise_data(ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG,
"maxsize=%ld", maxsize);
return -1;
}
/* Now work out minimal type (if any) */
if (traverse_string(in, len, inform, type_str, &mask) < 0) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_CHARACTERS);
return -1;
}
/*
* Now work out output format and string type.
* These checks should be in sync with the checks in type_str.
*/
outform = MBSTRING_ASC;
if (mask & B_ASN1_NUMERICSTRING)
str_type = V_ASN1_NUMERICSTRING;
else if (mask & B_ASN1_PRINTABLESTRING)
str_type = V_ASN1_PRINTABLESTRING;
else if (mask & B_ASN1_IA5STRING)
str_type = V_ASN1_IA5STRING;
else if (mask & B_ASN1_T61STRING)
str_type = V_ASN1_T61STRING;
else if (mask & B_ASN1_BMPSTRING) {
str_type = V_ASN1_BMPSTRING;
outform = MBSTRING_BMP;
} else if (mask & B_ASN1_UNIVERSALSTRING) {
str_type = V_ASN1_UNIVERSALSTRING;
outform = MBSTRING_UNIV;
} else {
str_type = V_ASN1_UTF8STRING;
outform = MBSTRING_UTF8;
}
if (!out)
return str_type;
if (*out) {
free_out = 0;
dest = *out;
ASN1_STRING_set0(dest, NULL, 0);
dest->type = str_type;
} else {
free_out = 1;
dest = ASN1_STRING_type_new(str_type);
if (dest == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
return -1;
}
*out = dest;
}
/* If both the same type just copy across */
if (inform == outform) {
if (!ASN1_STRING_set(dest, in, len)) {
if (free_out) {
ASN1_STRING_free(dest);
*out = NULL;
}
ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
return -1;
}
return str_type;
}
/* Work out how much space the destination will need */
switch (outform) {
case MBSTRING_ASC:
outlen = nchar;
cpyfunc = cpy_asc;
break;
case MBSTRING_BMP:
if (nchar > INT_MAX / 2) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG);
if (free_out) {
ASN1_STRING_free(dest);
*out = NULL;
}
return -1;
}
outlen = nchar << 1;
cpyfunc = cpy_bmp;
break;
case MBSTRING_UNIV:
if (nchar > INT_MAX / 4) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG);
if (free_out) {
ASN1_STRING_free(dest);
*out = NULL;
}
return -1;
}
outlen = nchar << 2;
cpyfunc = cpy_univ;
break;
case MBSTRING_UTF8:
outlen = 0;
ret = traverse_string(in, len, inform, out_utf8, &outlen);
if (ret < 0) { /* error already raised in out_utf8() */
if (free_out) {
ASN1_STRING_free(dest);
*out = NULL;
}
return -1;
}
cpyfunc = cpy_utf8;
break;
}
if ((p = OPENSSL_malloc(outlen + 1)) == NULL) {
if (free_out) {
ASN1_STRING_free(dest);
*out = NULL;
}
return -1;
}
dest->length = outlen;
dest->data = p;
p[outlen] = 0;
traverse_string(in, len, inform, cpyfunc, &p);
return str_type;
}