diff --git a/Makefile b/Makefile index d74e8bc..3cdcd7a 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ clean: $(MAKE) -C asn1-compiled lib-clean $(MAKE) -C src clean $(MAKE) -C tests clean + rm -rf project.tgz cov-int install: all mkdir -p $(DESTDIR)/$(HDR) @@ -31,4 +32,14 @@ install: all cp src/$(LIBSOVER) $(DESTDIR)/$(LIBDIR)/$(LIBSOVER) ln -s $(LIBSOVER) $(DESTDIR)/$(LIBDIR)/$(LIBSO) -.PHONY: all regenerate-asn1 clean install +coverity: + cov-build --dir cov-int $(MAKE) + tar -czf project.tgz cov-int + curl --form token=$(COVERITY_LIBTCAP_TOKEN) \ + --form email=$(DEBEMAIL) \ + --form file=@project.tgz \ + --form version="$(LIBTCAP_VERSION)" \ + --form description="automatic upload" \ + https://scan.coverity.com/builds?project=$(COVERITY_LIBTCAP_PROJECT) + +.PHONY: all regenerate-asn1 clean install coverity diff --git a/asn1-compiled/INTEGER.c b/asn1-compiled/INTEGER.c index 56d02b4..0ab29e4 100644 --- a/asn1-compiled/INTEGER.c +++ b/asn1-compiled/INTEGER.c @@ -996,6 +996,7 @@ asn_strtol_lim(const char *str, const char **end, long *lp) { case '-': last_digit_max++; sign = -1; + /* fall through */ case '+': str++; if(str >= *end) { diff --git a/asn1-compiled/OBJECT_IDENTIFIER.c b/asn1-compiled/OBJECT_IDENTIFIER.c index 066d562..2eaec9c 100644 --- a/asn1-compiled/OBJECT_IDENTIFIER.c +++ b/asn1-compiled/OBJECT_IDENTIFIER.c @@ -296,8 +296,10 @@ OBJECT_IDENTIFIER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const ret = OBJECT_IDENTIFIER_parse_arcs( (const char *)chunk_buf, chunk_size, arcs, arcs_count, &endptr); - if(ret != arcs_count) + if(ret != arcs_count) { + free(arcs); return XPBD_SYSTEM_FAILURE; /* assert?.. */ + } } /* diff --git a/asn1-compiled/OCTET_STRING.c b/asn1-compiled/OCTET_STRING.c index 584def8..3cb9d81 100644 --- a/asn1-compiled/OCTET_STRING.c +++ b/asn1-compiled/OCTET_STRING.c @@ -1594,6 +1594,9 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td, _ASN_ENCODE_FAILED; } + if(!st->buf) + _ASN_ENCODE_FAILED; + /* X.691, #16.5: zero-length encoding */ /* X.691, #16.6: short fixed length encoding (up to 2 octets) */ /* X.691, #16.7: long fixed length encoding (up to 64K octets) */ @@ -1712,16 +1715,18 @@ OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr, void OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { OCTET_STRING_t *st = (OCTET_STRING_t *)sptr; - asn_OCTET_STRING_specifics_t *specs = td->specifics - ? (asn_OCTET_STRING_specifics_t *)td->specifics - : &asn_DEF_OCTET_STRING_specs; - asn_struct_ctx_t *ctx = (asn_struct_ctx_t *) - ((char *)st + specs->ctx_offset); + asn_OCTET_STRING_specifics_t *specs; + asn_struct_ctx_t *ctx; struct _stack *stck; if(!td || !st) return; + specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + ctx = (asn_struct_ctx_t *) ((char *)st + specs->ctx_offset); + ASN_DEBUG("Freeing %s as OCTET STRING", td->name); if(st->buf) { diff --git a/asn1-compiled/constr_CHOICE.c b/asn1-compiled/constr_CHOICE.c index a9eb719..f0b5383 100644 --- a/asn1-compiled/constr_CHOICE.c +++ b/asn1-compiled/constr_CHOICE.c @@ -670,7 +670,6 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, case -1: ctx->phase = 5; RETURN(RC_FAIL); - continue; case 1: ctx->phase = 3; /* Fall through */ @@ -1029,12 +1028,14 @@ CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, void CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { - asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + asn_CHOICE_specifics_t *specs; int present; if(!td || !ptr) return; + specs = (asn_CHOICE_specifics_t *)td->specifics; + ASN_DEBUG("Freeing %s as CHOICE", td->name); /* diff --git a/asn1-compiled/constr_SEQUENCE.c b/asn1-compiled/constr_SEQUENCE.c index bc7f4ad..f23fb89 100644 --- a/asn1-compiled/constr_SEQUENCE.c +++ b/asn1-compiled/constr_SEQUENCE.c @@ -1149,8 +1149,10 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, if(!epres) _ASN_DECODE_STARVED; /* Get the extensions map */ - if(per_get_many_bits(pd, epres, 0, bmlength)) + if(per_get_many_bits(pd, epres, 0, bmlength)) { + free(epres); _ASN_DECODE_STARVED; + } memset(&epmd, 0, sizeof(epmd)); epmd.buffer = epres; diff --git a/asn1-compiled/per_encoder.c b/asn1-compiled/per_encoder.c index e76ef74..d7aae4f 100644 --- a/asn1-compiled/per_encoder.c +++ b/asn1-compiled/per_encoder.c @@ -123,7 +123,7 @@ uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constrain /* * Invoke type-specific encoder. */ - if(!td || !td->uper_encoder) + if(!(td && td->uper_encoder)) _ASN_ENCODE_FAILED; /* PER is not compiled in */ po.buffer = po.tmpspace; diff --git a/asn1-compiled/per_opentype.c b/asn1-compiled/per_opentype.c index 03a31d2..da26841 100644 --- a/asn1-compiled/per_opentype.c +++ b/asn1-compiled/per_opentype.c @@ -65,7 +65,8 @@ uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, asn_per_data_t spd; size_t padding; - _ASN_STACK_OVERFLOW_CHECK(ctx); + if(_ASN_STACK_OVERFLOW_CHECK(ctx)) + _ASN_DECODE_FAILED; ASN_DEBUG("Getting open type %s...", td->name); @@ -106,10 +107,10 @@ uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, if(rv.code == RC_OK) { /* Check padding validity */ padding = spd.nbits - spd.nboff; - if ((padding < 8 || + if ((padding < 8 || /* X.691#10.1.3 */ (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) && - per_get_few_bits(&spd, padding) == 0) { + per_get_few_bits(&spd, padding) == 0) { /* Everything is cool */ FREEMEM(buf); return rv; @@ -138,7 +139,8 @@ uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, asn_dec_rval_t rv; ssize_t padding; - _ASN_STACK_OVERFLOW_CHECK(ctx); + if(_ASN_STACK_OVERFLOW_CHECK(ctx)) + _ASN_DECODE_FAILED; ASN_DEBUG("Getting open type %s from %s", td->name, per_data_string(pd)); diff --git a/asn1-compiled/per_support.c b/asn1-compiled/per_support.c index 2481fff..4bd6318 100644 --- a/asn1-compiled/per_support.c +++ b/asn1-compiled/per_support.c @@ -12,7 +12,7 @@ per_data_string(asn_per_data_t *pd) { static char buf[2][32]; static int n; n = (n+1) % 2; - snprintf(buf[n], sizeof(buf), + snprintf(buf[n], sizeof(buf[n]), "{m=%ld span %+ld[%d..%d] (%d)}", (long)pd->moved, (((long)pd->buffer) & 0xf), @@ -342,8 +342,10 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) { buf[2] = bits >> 8, buf[3] = bits; else { - per_put_few_bits(po, bits >> (obits - 24), 24); - per_put_few_bits(po, bits, obits - 24); + if (obits >= 24) { /* probably a coverity false positive */ + per_put_few_bits(po, bits >> (obits - 24), 24); + per_put_few_bits(po, bits, obits - 24); + } } ASN_DEBUG("[PER out %u/%x => %02x buf+%ld]", diff --git a/asn1/postbuild-coverity.patch b/asn1/postbuild-coverity.patch new file mode 100644 index 0000000..25f47eb --- /dev/null +++ b/asn1/postbuild-coverity.patch @@ -0,0 +1,186 @@ +diff --git a/asn1-compiled/INTEGER.c b/asn1-compiled/INTEGER.c +index 56d02b4..0ab29e4 100644 +--- a/asn1-compiled/INTEGER.c ++++ b/asn1-compiled/INTEGER.c +@@ -996,6 +996,7 @@ asn_strtol_lim(const char *str, const char **end, long *lp) { + case '-': + last_digit_max++; + sign = -1; ++ /* fall through */ + case '+': + str++; + if(str >= *end) { +diff --git a/asn1-compiled/OBJECT_IDENTIFIER.c b/asn1-compiled/OBJECT_IDENTIFIER.c +index 066d562..2eaec9c 100644 +--- a/asn1-compiled/OBJECT_IDENTIFIER.c ++++ b/asn1-compiled/OBJECT_IDENTIFIER.c +@@ -296,8 +296,10 @@ OBJECT_IDENTIFIER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const + ret = OBJECT_IDENTIFIER_parse_arcs( + (const char *)chunk_buf, chunk_size, + arcs, arcs_count, &endptr); +- if(ret != arcs_count) ++ if(ret != arcs_count) { ++ free(arcs); + return XPBD_SYSTEM_FAILURE; /* assert?.. */ ++ } + } + + /* +diff --git a/asn1-compiled/OCTET_STRING.c b/asn1-compiled/OCTET_STRING.c +index 584def8..3cb9d81 100644 +--- a/asn1-compiled/OCTET_STRING.c ++++ b/asn1-compiled/OCTET_STRING.c +@@ -1594,6 +1594,9 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td, + _ASN_ENCODE_FAILED; + } + ++ if(!st->buf) ++ _ASN_ENCODE_FAILED; ++ + /* X.691, #16.5: zero-length encoding */ + /* X.691, #16.6: short fixed length encoding (up to 2 octets) */ + /* X.691, #16.7: long fixed length encoding (up to 64K octets) */ +@@ -1712,16 +1715,18 @@ OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr, + void + OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { + OCTET_STRING_t *st = (OCTET_STRING_t *)sptr; +- asn_OCTET_STRING_specifics_t *specs = td->specifics +- ? (asn_OCTET_STRING_specifics_t *)td->specifics +- : &asn_DEF_OCTET_STRING_specs; +- asn_struct_ctx_t *ctx = (asn_struct_ctx_t *) +- ((char *)st + specs->ctx_offset); ++ asn_OCTET_STRING_specifics_t *specs; ++ asn_struct_ctx_t *ctx; + struct _stack *stck; + + if(!td || !st) + return; + ++ specs = td->specifics ++ ? (asn_OCTET_STRING_specifics_t *)td->specifics ++ : &asn_DEF_OCTET_STRING_specs; ++ ctx = (asn_struct_ctx_t *) ((char *)st + specs->ctx_offset); ++ + ASN_DEBUG("Freeing %s as OCTET STRING", td->name); + + if(st->buf) { +diff --git a/asn1-compiled/constr_CHOICE.c b/asn1-compiled/constr_CHOICE.c +index a9eb719..f0b5383 100644 +--- a/asn1-compiled/constr_CHOICE.c ++++ b/asn1-compiled/constr_CHOICE.c +@@ -670,7 +670,6 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + case -1: + ctx->phase = 5; + RETURN(RC_FAIL); +- continue; + case 1: + ctx->phase = 3; + /* Fall through */ +@@ -1029,12 +1028,14 @@ CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + + void + CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { +- asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; ++ asn_CHOICE_specifics_t *specs; + int present; + + if(!td || !ptr) + return; + ++ specs = (asn_CHOICE_specifics_t *)td->specifics; ++ + ASN_DEBUG("Freeing %s as CHOICE", td->name); + + /* +diff --git a/asn1-compiled/constr_SEQUENCE.c b/asn1-compiled/constr_SEQUENCE.c +index bc7f4ad..f23fb89 100644 +--- a/asn1-compiled/constr_SEQUENCE.c ++++ b/asn1-compiled/constr_SEQUENCE.c +@@ -1149,8 +1149,10 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + if(!epres) _ASN_DECODE_STARVED; + + /* Get the extensions map */ +- if(per_get_many_bits(pd, epres, 0, bmlength)) ++ if(per_get_many_bits(pd, epres, 0, bmlength)) { ++ free(epres); + _ASN_DECODE_STARVED; ++ } + + memset(&epmd, 0, sizeof(epmd)); + epmd.buffer = epres; +diff --git a/asn1-compiled/per_encoder.c b/asn1-compiled/per_encoder.c +index e76ef74..d7aae4f 100644 +--- a/asn1-compiled/per_encoder.c ++++ b/asn1-compiled/per_encoder.c +@@ -123,7 +123,7 @@ uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constrain + /* + * Invoke type-specific encoder. + */ +- if(!td || !td->uper_encoder) ++ if(!(td && td->uper_encoder)) + _ASN_ENCODE_FAILED; /* PER is not compiled in */ + + po.buffer = po.tmpspace; +diff --git a/asn1-compiled/per_opentype.c b/asn1-compiled/per_opentype.c +index 03a31d2..da26841 100644 +--- a/asn1-compiled/per_opentype.c ++++ b/asn1-compiled/per_opentype.c +@@ -65,7 +65,8 @@ uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, + asn_per_data_t spd; + size_t padding; + +- _ASN_STACK_OVERFLOW_CHECK(ctx); ++ if(_ASN_STACK_OVERFLOW_CHECK(ctx)) ++ _ASN_DECODE_FAILED; + + ASN_DEBUG("Getting open type %s...", td->name); + +@@ -106,10 +107,10 @@ uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, + if(rv.code == RC_OK) { + /* Check padding validity */ + padding = spd.nbits - spd.nboff; +- if ((padding < 8 || ++ if ((padding < 8 || + /* X.691#10.1.3 */ + (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) && +- per_get_few_bits(&spd, padding) == 0) { ++ per_get_few_bits(&spd, padding) == 0) { + /* Everything is cool */ + FREEMEM(buf); + return rv; +@@ -138,7 +139,8 @@ uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, + asn_dec_rval_t rv; + ssize_t padding; + +- _ASN_STACK_OVERFLOW_CHECK(ctx); ++ if(_ASN_STACK_OVERFLOW_CHECK(ctx)) ++ _ASN_DECODE_FAILED; + + ASN_DEBUG("Getting open type %s from %s", td->name, + per_data_string(pd)); +diff --git a/asn1-compiled/per_support.c b/asn1-compiled/per_support.c +index 2481fff..4bd6318 100644 +--- a/asn1-compiled/per_support.c ++++ b/asn1-compiled/per_support.c +@@ -12,7 +12,7 @@ per_data_string(asn_per_data_t *pd) { + static char buf[2][32]; + static int n; + n = (n+1) % 2; +- snprintf(buf[n], sizeof(buf), ++ snprintf(buf[n], sizeof(buf[n]), + "{m=%ld span %+ld[%d..%d] (%d)}", + (long)pd->moved, + (((long)pd->buffer) & 0xf), +@@ -342,8 +342,10 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) { + buf[2] = bits >> 8, + buf[3] = bits; + else { +- per_put_few_bits(po, bits >> (obits - 24), 24); +- per_put_few_bits(po, bits, obits - 24); ++ if (obits >= 24) { /* probably a coverity false positive */ ++ per_put_few_bits(po, bits >> (obits - 24), 24); ++ per_put_few_bits(po, bits, obits - 24); ++ } + } + + ASN_DEBUG("[PER out %u/%x => %02x buf+%ld]", diff --git a/src/tcap.c b/src/tcap.c index 33b9201..5feaa6e 100644 --- a/src/tcap.c +++ b/src/tcap.c @@ -111,7 +111,8 @@ void *inap_decode(Invoke_t *invoke, asn_TYPE_descriptor_t **type) { (*type)->free_struct(*type, arg, 0); nothing: - *type = NULL; + if(type) + *type = NULL; return NULL; } @@ -330,7 +331,7 @@ error: static inline char phone_digit(unsigned char d) { - if (d >= 0 && d <= 9) + if (d <= 9) return '0' + d; switch (d) { case 11: @@ -345,7 +346,7 @@ static inline char phone_digit(unsigned char d) { } static inline char phone_digit_hex(unsigned char d) { - if (d >= 0 && d <= 9) + if (d <= 9) return '0' + d; else if (d >= 10 && d <= 15) return 'A' + d - 10; diff --git a/tests/encode.c b/tests/encode.c index 6dd5715..76d8359 100644 --- a/tests/encode.c +++ b/tests/encode.c @@ -47,7 +47,11 @@ int main() { ret = tcap_encode(&buf, &msg); fprintf(stderr, "ret: %i\n", ret); - fwrite(buf, ret, 1, stdout); + if(ret < 0) { + fprintf(stderr, "failed to encode tcap\n"); + } else { + fwrite(buf, ret, 1, stdout); + } free(buf); asn_DEF_ANY.free_struct(&asn_DEF_ANY, cmp.choice.invoke.parameter, 0);