mouse07410 / asn1c

The ASN.1 Compiler
http://lionet.info/asn1c/
BSD 2-Clause "Simplified" License
97 stars 71 forks source link

Enumerated constraints appear broken #119

Open bknotwell opened 1 year ago

bknotwell commented 1 year ago

The NativeEnumerated_constraint is defined to asm_generic_no_constraint. Not sure if this is intentional or not but I've attached a minimal example below to illustrate the issue:

FruitModule DEFINITIONS ::=

BEGIN
FruitId ::= ENUMERATED { apple(1), orange(2) }

Fruit ::= SEQUENCE {
   fruit FruitId
}
END
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <Fruit.h>

int main(void) {
    Fruit_t fruit;
    Fruit_t fruitbad;
    int ret;
    char errbuf[128];
    size_t errlen = sizeof(errbuf);

    memset(&fruit, 0, sizeof(Fruit_t));
    memset(&fruitbad, 0, sizeof(Fruit_t));

    fruit.fruit = FruitId_orange;
    fruitbad.fruit = 42;

    ret = asn_check_constraints(&asn_DEF_Fruit, &fruit,
                                errbuf, &errlen);
    if(ret) {
        fprintf(stderr, "Fruit validation failed(unexpected): %s\n", errbuf);
    }
    ret = asn_check_constraints(&asn_DEF_Fruit, &fruitbad,
                                errbuf, &errlen);
    if(ret) {
        fprintf(stderr, "Fruitbad validation failed(expected): %s\n", errbuf);
    }
    return 0; 
}
bknotwell commented 1 year ago

The second fprintf should execute but it doesn't as the second constraints check returns zero.

bknotwell commented 1 year ago

While the following program does what I want, I don't know if it's architecturally correct. If it's not, it's a workaround for a bug. Otherwise, I'd recommend updating the user's guide to show three things:

#include <string.h>
#include <sys/types.h>
#include <Fruit.h>

static int validate_fruit(const asn_TYPE_descriptor_t *td, const void *sptr,
                          asn_app_constraint_failed_f *ctfailcb, void* app_key) {
    long value;
    if(! sptr) {
        ASN__CTFAIL(app_key, td, sptr,
                    "%s: value not given (%s:%d)",
                    td->name, __FILE__, __LINE__);
        return -1;
    }

    value = *(const long*)sptr;

    if(value == FruitId_orange || value == FruitId_apple)
        return 0;

    ASN__CTFAIL(app_key, td, sptr,
                "%s: constraint failed (%s:%d)",
                td->name, __FILE__, __LINE__);
    return -1;
}

int main(void) {
    Fruit_t fruit;
    Fruit_t fruitbad;
    int ret;
    char errbuf[128];
    size_t errlen = sizeof(errbuf);

    memset(&fruit, 0, sizeof(Fruit_t));
    memset(&fruitbad, 0, sizeof(Fruit_t));

    fruit.fruit = FruitId_orange;;
    fruitbad.fruit = 42;

    asn_DEF_Fruit.elements[0].encoding_constraints.general_constraints = validate_fruit;

    ret = asn_check_constraints(&asn_DEF_Fruit, &fruit,
                                errbuf, &errlen);
    if(ret)
        fprintf(stderr, "Fruit validation failed(unexpected): %s\n", errbuf);

    ret = asn_check_constraints(&asn_DEF_Fruit, &fruitbad,
                                errbuf, &errlen);
    if(ret)
        fprintf(stderr, "Fruitbad validation failed(expected): %s\n", errbuf);

    return 0; 
}
bknotwell commented 1 year ago

Thinking about it a bit, there is an easy way to generate validators for enums that requires zero cleverness in the code generator--build a switch statement and avoid the difficulty of assembling a correct set of if statements.:

static int validate_fruit(const asn_TYPE_descriptor_t *td, const void *sptr,
                          asn_app_constraint_failed_f *ctfailcb, void* app_key) {
    e_FruitId value;
    if(! sptr) {
        ASN__CTFAIL(app_key, td, sptr,
                    "%s: value not given (%s:%d)",
                    td->name, __FILE__, __LINE__);
        return -1;
    }

    value = *(e_FruitId*)sptr;

    switch(value) {
    case FruitId_orange:
    case FruitId_apple:
        return 0;
    }

    ASN__CTFAIL(app_key, td, sptr,
                "%s: constraint failed (%s:%d)",
                td->name, __FILE__, __LINE__);
    return -1;
}
mouse07410 commented 1 year ago

@bknotwell thanks for reporting. Would you consider submitting a PR?

mtbakerguy commented 1 year ago

I'll take a look at the code. I suspect it'll be doable.

bknotwell commented 1 year ago

https://github.com/mouse07410/asn1c/pull/121

mouse07410 commented 1 year ago

To speed up merging of #121, could you please fix the CI, so it passes the tests?