Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enumerated constraints appear broken #119

Open
bknotwell opened this issue Feb 11, 2023 · 7 comments
Open

Enumerated constraints appear broken #119

bknotwell opened this issue Feb 11, 2023 · 7 comments

Comments

@bknotwell
Copy link

bknotwell commented Feb 11, 2023

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
Copy link
Author

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

@bknotwell
Copy link
Author

bknotwell commented Feb 12, 2023

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:

  • how to write custom validators for enumerated values.
  • that you need to count N fields forward to set the correct general_constraints function pointer. NOTE: a less ugly way to do this would add something like #define fruitId 0 to the Fruit.h file so developers would put the field name in the elements array instead of the raw integer.
  • the function protocol for the general_constraints call.
#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
Copy link
Author

bknotwell commented Feb 12, 2023

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
Copy link
Owner

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

@mtbakerguy
Copy link

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

@bknotwell
Copy link
Author

#121

@mouse07410
Copy link
Owner

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants