summaryrefslogtreecommitdiffstats
path: root/asn1/asn1c/constraints.c
blob: 74cbaf8675afaad722e831a7c3a21474109ad8c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include "asn_internal.h"
#include "constraints.h"

int asn_generic_no_constraint(asn_TYPE_descriptor_t * type_descriptor,
                              const void *struct_ptr,
                              asn_app_constraint_failed_f * cb, void *key)
{

    (void)type_descriptor;      /* Unused argument */
    (void)struct_ptr;           /* Unused argument */
    (void)cb;                   /* Unused argument */
    (void)key;                  /* Unused argument */

    /* Nothing to check */
    return 0;
}

int asn_generic_unknown_constraint(asn_TYPE_descriptor_t * type_descriptor,
                                   const void *struct_ptr,
                                   asn_app_constraint_failed_f * cb, void *key)
{

    (void)type_descriptor;      /* Unused argument */
    (void)struct_ptr;           /* Unused argument */
    (void)cb;                   /* Unused argument */
    (void)key;                  /* Unused argument */

    /* Unknown how to check */
    return 0;
}

struct errbufDesc {
    asn_TYPE_descriptor_t *failed_type;
    const void *failed_struct_ptr;
    char *errbuf;
    size_t errlen;
};

static void _asn_i_ctfailcb(void *key, asn_TYPE_descriptor_t * td,
                            const void *sptr, const char *fmt, ...)
{
    struct errbufDesc *arg = key;
    va_list ap;
    ssize_t vlen;
    ssize_t maxlen;

    arg->failed_type = td;
    arg->failed_struct_ptr = sptr;

    maxlen = arg->errlen;
    if (maxlen <= 0)
        return;

    va_start(ap, fmt);
    vlen = vsnprintf(arg->errbuf, maxlen, fmt, ap);
    va_end(ap);
    if (vlen >= maxlen) {
        arg->errbuf[maxlen - 1] = '\0'; /* Ensuring libc correctness */
        arg->errlen = maxlen - 1;       /* Not counting termination */
        return;
    } else if (vlen >= 0) {
        arg->errbuf[vlen] = '\0';       /* Ensuring libc correctness */
        arg->errlen = vlen;     /* Not counting termination */
    } else {
        /*
         * The libc on this system is broken.
         */
        vlen = sizeof("<broken vsnprintf>") - 1;
        maxlen--;
        arg->errlen = vlen < maxlen ? vlen : maxlen;
        memcpy(arg->errbuf, "<broken vsnprintf>", arg->errlen);
        arg->errbuf[arg->errlen] = 0;
    }

    return;
}

int asn_check_constraints(asn_TYPE_descriptor_t * type_descriptor,
                          const void *struct_ptr, char *errbuf,
                          size_t * errlen)
{
    struct errbufDesc arg;
    int ret;

    arg.failed_type = 0;
    arg.failed_struct_ptr = 0;
    arg.errbuf = errbuf;
    arg.errlen = errlen ? *errlen : 0;

    ret =
        type_descriptor->check_constraints(type_descriptor, struct_ptr,
                                           _asn_i_ctfailcb, &arg);
    if (ret == -1 && errlen)
        *errlen = arg.errlen;

    return ret;
}