#include <openssl/asn1.h>
#include <openssl/rand.h>
#include <string.h>
#include <stdio.h>
#include "opensslbug.h"

ASN1_SEQUENCE(REQTEST) = {
    ASN1_IMP_OPT(REQTEST, badstring, GENERAL_NAME, 0),
    ASN1_IMP_OPT(REQTEST, mystr, ASN1_UTF8STRING, 1)
} ASN1_SEQUENCE_END(REQTEST)

IMPLEMENT_ASN1_FUNCTIONS(REQTEST)

ASN1_SEQUENCE(REQTEST2) = {
    ASN1_IMP_OPT(REQTEST2, badstring, ASN1_UTF8STRING, 0),
    ASN1_IMP_OPT(REQTEST2, mystr, ASN1_UTF8STRING, 1)
} ASN1_SEQUENCE_END(REQTEST2)

IMPLEMENT_ASN1_FUNCTIONS(REQTEST2)

int REQTEST_set_mystr(REQTEST *req, const char *text)
{
    int len = strlen(text);
    unsigned char *req_text;

    if (text == NULL || req == NULL)
    {
        return 0;
    }

    req_text = (unsigned char *)text;
    if (req->mystr)
    {
        ASN1_UTF8STRING_free(req->mystr);
        req->mystr = NULL;
    }

    req->mystr = ASN1_UTF8STRING_new();

    if (req->mystr == NULL)
    {
        return 0;
    }
    return ASN1_STRING_set(req->mystr, req_text, len);
}

int REQTEST2_set_mystr(REQTEST2 *req, const char *text)
{
    int len = strlen(text);
    unsigned char *req_text;

    if (text == NULL || req == NULL)
    {
        return 0;
    }

    req_text = (unsigned char *)text;
    if (req->mystr)
    {
        ASN1_UTF8STRING_free(req->mystr);
        req->mystr = NULL;
    }

    req->mystr = ASN1_UTF8STRING_new();

    if (req->mystr == NULL)
    {
        return 0;
    }
    return ASN1_STRING_set(req->mystr, req_text, len);
}

void errors(int d)
{
    unsigned long err = 0;
    while ((err = ERR_get_error()) != 0)
    {
        printf("%d: %s\n", d, ERR_error_string(err, NULL));
    }
}

int main()
{
    ERR_load_crypto_strings();
    ERR_load_BIO_strings();
    OpenSSL_add_all_algorithms();

    REQTEST *r = REQTEST_new();
    REQTEST_set_mystr(r, "chickens");

    errors(1);
    BIO *b = BIO_new(BIO_s_mem());
    errors(2);
    i2d_REQTEST_bio(b, r);
    errors(3);
    REQTEST *r2 = d2i_REQTEST_bio(b, NULL);
    errors(4);

    REQTEST2 *r3 = REQTEST2_new();
    REQTEST2_set_mystr(r3, "chickens");

    errors(1);
    BIO *b2 = BIO_new(BIO_s_mem());
    errors(2);
    i2d_REQTEST2_bio(b2, r3);
    errors(3);
    REQTEST2 *r4 = d2i_REQTEST2_bio(b2, NULL);
    errors(4);

    return 0;
}
