diff -ruN net-snmp-5.2.1.2.orig/snmplib/asn1.c net-snmp-5.2.1.2/snmplib/asn1.c --- net-snmp-5.2.1.2.orig/snmplib/asn1.c 2004-12-10 15:07:16.000000000 +0000 +++ net-snmp-5.2.1.2/snmplib/asn1.c 2007-02-17 23:54:03.000000000 +0000 @@ -470,6 +470,13 @@ while (asn_length--) value = (value << 8) | *bufp++; +/*#if SIZEOF_LONG != 4 + if ((unsigned long)value > 0xffffffff) { + snmp_log(LOG_ERR,"truncating integer value to 32 bits\n"); + value &= 0xffffffff; + } +#endif*/ + DEBUGMSG(("dumpv_recv", " Integer:\t%ld (0x%.2X)\n", value, value)); *intp = value; @@ -535,6 +542,13 @@ while (asn_length--) value = (value << 8) | *bufp++; +#if SIZEOF_LONG != 4 + if (value > 0xffffffff) { + snmp_log(LOG_ERR,"truncating uinteger value to 32 bits\n"); + value &= 0xffffffff; + } +#endif + DEBUGMSG(("dumpv_recv", " UInteger:\t%ld (0x%.2X)\n", value, value)); *intp = value; @@ -584,6 +598,12 @@ return NULL; } integer = *intp; +#if SIZEOF_LONG != 4 + if ((unsigned long)integer > 0xffffffff) { + snmp_log(LOG_ERR,"truncating integer value to 32 bits\n"); + integer &= 0xffffffff; + } +#endif /* * Truncate "unnecessary" bytes off of the most significant end of this * 2's complement integer. There should be no sequence of 9 @@ -663,6 +683,12 @@ return NULL; } integer = *intp; +#if SIZEOF_LONG != 4 + if (integer > 0xffffffff) { + snmp_log(LOG_ERR,"truncating uinteger value to 32 bits\n"); + integer &= 0xffffffff; + } +#endif mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); /* * mask is 0xFF000000 on a big-endian machine @@ -1286,18 +1312,13 @@ (subidentifier << 7) + (*(u_char *) bufp & ~ASN_BIT8); length--; } while (*(u_char *) bufp++ & ASN_BIT8); /* last byte has high bit clear */ - /* - * ?? note, this test will never be true, since the largest value - * of subidentifier is the value of MAX_SUBID! - * - * Yes: PC-LINT says the same thing - * No!: the agent can be configured to use a char instead of a long - * for OIDs, in which case this test is essential. - */ + +#if defined(EIGHTBIT_SUBIDS) || (SIZEOF_LONG != 4) if (subidentifier > (u_long) MAX_SUBID) { ERROR_MSG("subidentifier too large"); return NULL; } +#endif *oidp++ = (oid) subidentifier; } @@ -1439,6 +1460,12 @@ if (i >= (int) objidlength) break; objid_val = *op++; /* XXX - doesn't handle 2.X (X > 40) */ +#if SIZEOF_LONG != 4 + if (objid_val > 0xffffffff) { + snmp_log(LOG_ERR,"truncating objid value to 32 bits\n"); + objid_val &= 0xffffffff; + } +#endif } /* @@ -1454,8 +1481,13 @@ */ for (i = 1, objid_val = first_objid_val, op = objid + 2; i < (int) objidlength; i++) { - if (i != 1) + if (i != 1) { objid_val = *op++; +#if SIZEOF_LONG != 4 + if (objid_val > 0xffffffff) /* already logged warning above */ + objid_val &= 0xffffffff; +#endif + } switch (objid_size[i]) { case 1: *data++ = (u_char) objid_val; @@ -1783,6 +1815,17 @@ low = (low << 8) | *bufp++; } +#if SIZEOF_LONG != 4 + if (high > 0xffffffff) { + snmp_log(LOG_ERR,"truncating counter64 high value to 32 bits\n"); + high &= 0xffffffff; + } + if (low > 0xffffffff) { + snmp_log(LOG_ERR,"truncating counter64 low value to 32 bits\n"); + low &= 0xffffffff; + } +#endif + cp->low = low; cp->high = high; @@ -1843,6 +1886,16 @@ intsize = 8; low = cp->low; high = cp->high; +#if SIZEOF_LONG != 4 + if (high > 0xffffffff) { + snmp_log(LOG_ERR,"truncating counter64 high value to 32 bits\n"); + high &= 0xffffffff; + } + if (low > 0xffffffff) { + snmp_log(LOG_ERR,"truncating counter64 low value to 32 bits\n"); + low &= 0xffffffff; + } +#endif mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); /* * mask is 0xFF000000 on a big-endian machine @@ -2041,6 +2094,17 @@ low = (low << 8) | *bufp++; } +#if SIZEOF_LONG != 4 + if (high > 0xffffffff) { + snmp_log(LOG_ERR,"truncating counter64 high value to 32 bits\n"); + high &= 0xffffffff; + } + if (low > 0xffffffff) { + snmp_log(LOG_ERR,"truncating counter64 low value to 32 bits\n"); + low &= 0xffffffff; + } +#endif + cp->low = low; cp->high = high; @@ -2103,6 +2167,16 @@ memcpy(&c64, cp, sizeof(struct counter64)); /* we're may modify it */ low = c64.low; high = c64.high; +#if SIZEOF_LONG != 4 + if (high > 0xffffffff) { + snmp_log(LOG_ERR,"truncating counter64 high value to 32 bits\n"); + high &= 0xffffffff; + } + if (low > 0xffffffff) { + snmp_log(LOG_ERR,"truncating counter64 low value to 32 bits\n"); + low &= 0xffffffff; + } +#endif /* * Truncate "unnecessary" bytes off of the most significant end of this @@ -2673,6 +2747,12 @@ _asn_size_err(errpre, intsize, sizeof(long)); return 0; } +#if SIZEOF_LONG != 4 + if ((unsigned long)integer > 0xffffffff) { + snmp_log(LOG_ERR,"truncating integer value to 32 bits\n"); + integer &= 0xffffffff; + } +#endif if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) { return 0; @@ -2825,6 +2905,13 @@ return 0; } +#if SIZEOF_LONG != 4 + if (integer > 0xffffffff) { + snmp_log(LOG_ERR,"truncating uinteger value to 32 bits\n"); + integer &= 0xffffffff; + } +#endif + if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) { return 0; } @@ -2960,6 +3047,12 @@ } else { for (i = objidlength; i > 2; i--) { tmpint = objid[i - 1]; +#if SIZEOF_LONG != 4 + if ((unsigned long)tmpint > 0xffffffff) { + snmp_log(LOG_ERR,"truncating oid subid to 32 bits\n"); + tmpint &= 0xffffffff; + } +#endif if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) { @@ -3176,6 +3269,16 @@ sizeof(struct counter64)); return 0; } +#if SIZEOF_LONG != 4 + if (high > 0xffffffff) { + snmp_log(LOG_ERR,"truncating counter64 high value to 32 bits\n"); + high &= 0xffffffff; + } + if (low > 0xffffffff) { + snmp_log(LOG_ERR,"truncating counter64 low value to 32 bits\n"); + low &= 0xffffffff; + } +#endif /* * Encode the low 4 bytes first. @@ -3359,6 +3462,17 @@ return 0; } +#if SIZEOF_LONG != 4 + if (high > 0xffffffff) { + snmp_log(LOG_ERR,"truncating counter64 high value to 32 bits\n"); + high &= 0xffffffff; + } + if (low > 0xffffffff) { + snmp_log(LOG_ERR,"truncating counter64 low value to 32 bits\n"); + low &= 0xffffffff; + } +#endif + /* * Encode the low 4 bytes first. */ diff -ruN net-snmp-5.2.1.2.orig/snmplib/int64.c net-snmp-5.2.1.2/snmplib/int64.c --- net-snmp-5.2.1.2.orig/snmplib/int64.c 2004-07-11 04:28:45.000000000 +0000 +++ net-snmp-5.2.1.2/snmplib/int64.c 2007-02-17 23:54:03.000000000 +0000 @@ -179,7 +179,9 @@ */ pu64->low = (ulT1 + u16) & 0x0FFFFFFFFL; pu64->high++; - +#if SIZEOF_LONG != 4 + pu64->high &= 0xffffffff; +#endif } /* incrByV16 */ void @@ -188,8 +190,15 @@ unsigned int tmp; tmp = pu64->low; pu64->low += u32; - if (pu64->low < tmp) +#if SIZEOF_LONG != 4 + pu64->low &= 0xffffffff; +#endif + if (pu64->low < tmp) { pu64->high++; +#if SIZEOF_LONG != 4 + pu64->high &= 0xffffffff; +#endif + } } /** @@ -214,6 +223,9 @@ u64Incr(U64 * pu64out, const U64 * pu64one) { pu64out->high += pu64one->high; +#if SIZEOF_LONG != 4 + pu64out->high &= 0xffffffff; +#endif incrByU32(pu64out, pu64one->low); } @@ -247,7 +259,6 @@ void zeroU64(U64 * pu64) { - pu64->low = 0; pu64->high = 0; } /* zeroU64 */ @@ -315,8 +326,12 @@ */ if (new_val->high == old_val->high) { DEBUGMSGTL(("c64:check_wrap", "32 bit wrap\n")); - if (adjust) + if (adjust) { ++new_val->high; +#if SIZEOF_LONG != 4 + new_val->high &= 0xffffffff; +#endif + } return 32; } else if ((new_val->high == (old_val->high + 1)) || diff -ruN net-snmp-5.2.1.2.orig/snmplib/snmp_client.c net-snmp-5.2.1.2/snmplib/snmp_client.c --- net-snmp-5.2.1.2.orig/snmplib/snmp_client.c 2004-12-10 02:21:38.000000000 +0000 +++ net-snmp-5.2.1.2/snmplib/snmp_client.c 2007-02-17 23:54:43.000000000 +0000 @@ -94,6 +94,7 @@ #include #include +#include #include #include @@ -714,41 +715,193 @@ */ int -snmp_set_var_value(netsnmp_variable_list * newvar, - const u_char * val_str, size_t val_len) +snmp_set_var_value(netsnmp_variable_list * vars, + const u_char * value, size_t len) { + int largeval = 1; + /* * xxx-rks: why the unconditional free? why not use existing - * memory, if val_len < newvar->val_len ? + * memory, if len < vars->val_len ? */ - if (newvar->val.string && newvar->val.string != newvar->buf) { - free(newvar->val.string); + if (vars->val.string && vars->val.string != vars->buf) { + free(vars->val.string); } - - newvar->val.string = 0; - newvar->val_len = 0; + vars->val.string = 0; + vars->val_len = 0; /* - * need a pointer and a length to copy a string value. + * use built-in storage for smaller values */ - if (val_str && val_len) { - if (val_len <= sizeof(newvar->buf)) - newvar->val.string = newvar->buf; - else { - newvar->val.string = (u_char *) malloc(val_len); - if (!newvar->val.string) - return 1; - } - memmove(newvar->val.string, val_str, val_len); - newvar->val_len = val_len; - } else if (val_str) { + if (len <= (sizeof(vars->buf) - 1)) { + vars->val.string = (u_char *) vars->buf; + largeval = 0; + } + + if ((0 == len) || (NULL == value)) { + vars->val.string[0] = 0; + return 0; + } + + vars->val_len = len; + switch (vars->type) { + case ASN_INTEGER: + case ASN_UNSIGNED: + case ASN_TIMETICKS: + case ASN_IPADDRESS: + case ASN_COUNTER: + if (value) { + if (vars->val_len == sizeof(int)) { + if (ASN_INTEGER == vars->type) { + const int *val_int + = (const int *) value; + *(vars->val.integer) = (long) *val_int; + } else { + const u_int *val_uint + = (const u_int *) value; + *(vars->val.integer) = (unsigned long) *val_uint; + } + } +#if SIZEOF_LONG != SIZEOF_INT + else if (vars->val_len == sizeof(long)){ + const u_long *val_ulong + = (const u_long *) value; + *(vars->val.integer) = *val_ulong; + if (*(vars->val.integer) > 0xffffffff) { + snmp_log(LOG_ERR,"truncating integer value > 32 bits\n"); + *(vars->val.integer) &= 0xffffffff; + } + } +#endif +#if SIZEOF_LONG != SIZEOF_LONG_LONG + else if (vars->val_len == sizeof(long long)){ + const unsigned long long *val_ullong + = (const unsigned long long *) value; + *(vars->val.integer) = (long) *val_ullong; + if (*(vars->val.integer) > 0xffffffff) { + snmp_log(LOG_ERR,"truncating integer value > 32 bits\n"); + *(vars->val.integer) &= 0xffffffff; + } + } +#endif +#if SIZEOF_SHORT != SIZEOF_INT + else if (vars->val_len == sizeof(short)) { + if (ASN_INTEGER == vars->type) { + const short *val_short + = (const short *) value; + *(vars->val.integer) = (long) *val_short; + } else { + const u_short *val_ushort + = (const u_short *) value; + *(vars->val.integer) = (unsigned long) *val_ushort; + } + } +#endif + else if (vars->val_len == sizeof(char)) { + if (ASN_INTEGER == vars->type) { + const char *val_char + = (const char *) value; + *(vars->val.integer) = (long) *val_char; + } else { + *(vars->val.integer) = (unsigned long) *value; + } + } + else { + snmp_log(LOG_ERR,"bad size for integer-like type (%d)\n", + vars->val_len); + return (1); + } + } else + *(vars->val.integer) = 0; + vars->val_len = sizeof(long); + break; + + case ASN_OBJECT_ID: + case ASN_PRIV_IMPLIED_OBJECT_ID: + case ASN_PRIV_INCL_RANGE: + case ASN_PRIV_EXCL_RANGE: + if (largeval) { + vars->val.objid = (oid *) malloc(vars->val_len); + } + if (vars->val.objid == NULL) { + snmp_log(LOG_ERR,"no storage for OID\n"); + return 1; + } + memmove(vars->val.objid, value, vars->val_len); + break; + + case ASN_PRIV_IMPLIED_OCTET_STR: + case ASN_OCTET_STR: + case ASN_BIT_STR: + case ASN_OPAQUE: + case ASN_NSAP: + if (largeval) { + vars->val.string = (u_char *) malloc(vars->val_len + 1); + } + if (vars->val.string == NULL) { + snmp_log(LOG_ERR,"no storage for OID\n"); + return 1; + } + memmove(vars->val.string, value, vars->val_len); /* - * NULL STRING != NULL ptr + * Make sure the string is zero-terminated; some bits of code make + * this assumption. Easier to do this here than fix all these wrong + * assumptions. */ - newvar->val.string = newvar->buf; - newvar->val.string[0] = '\0'; - newvar->val_len = 0; + vars->val.string[vars->val_len] = '\0'; + break; + + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + vars->val_len = 0; + vars->val.string = NULL; + break; + +#ifdef OPAQUE_SPECIAL_TYPES + case ASN_OPAQUE_U64: + case ASN_OPAQUE_I64: +#endif /* OPAQUE_SPECIAL_TYPES */ + case ASN_COUNTER64: + if (largeval) { + snmp_log(LOG_ERR,"bad size for counter 64 (%d)\n", + vars->val_len); + return (1); + } + vars->val_len = sizeof(struct counter64); + memmove(vars->val.counter64, value, vars->val_len); + break; + +#ifdef OPAQUE_SPECIAL_TYPES + case ASN_OPAQUE_FLOAT: + if (largeval) { + snmp_log(LOG_ERR,"bad size for opaque float (%d)\n", + vars->val_len); + return (1); + } + vars->val_len = sizeof(float); + memmove(vars->val.floatVal, value, vars->val_len); + break; + + case ASN_OPAQUE_DOUBLE: + if (largeval) { + snmp_log(LOG_ERR,"bad size for opaque double (%d)\n", + vars->val_len); + return (1); + } + vars->val_len = sizeof(double); + memmove(vars->val.doubleVal, value, vars->val_len); + break; + +#endif /* OPAQUE_SPECIAL_TYPES */ + + default: + snmp_log(LOG_ERR,"no storage for OID\n"); + snmp_set_detail("Internal error in type switching\n"); + return (1); } + return 0; }