- long ltmp;
- unsigned long utmp;
- int clen, pad, i;
- /* this exists to bypass broken gcc optimization */
- char *cp = (char *)pval;
-
- /* use memcpy, because we may not be long aligned */
- memcpy(<mp, cp, sizeof(long));
-
- if(ltmp == it->size) return -1;
- /* Convert the long to positive: we subtract one if negative so
- * we can cleanly handle the padding if only the MSB of the leading
- * octet is set.
- */
- if(ltmp < 0) utmp = -ltmp - 1;
- else utmp = ltmp;
- clen = BN_num_bits_word(utmp);
- /* If MSB of leading octet set we need to pad */
- if(!(clen & 0x7)) pad = 1;
- else pad = 0;
-
- /* Convert number of bits to number of octets */
- clen = (clen + 7) >> 3;
-
- if(cont) {
- if(pad) *cont++ = (ltmp < 0) ? 0xff : 0;
- for(i = clen - 1; i >= 0; i--) {
- cont[i] = (unsigned char)(utmp & 0xff);
- if(ltmp < 0) cont[i] ^= 0xff;
- utmp >>= 8;
- }
- }
- return clen + pad;
+ int neg, i;
+ long ltmp;
+ unsigned long utmp = 0;
+ char *cp = (char *)pval;
+ if (len > (int)sizeof(long)) {
+ ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+ return 0;
+ }
+ /* Is it negative? */
+ if (len && (cont[0] & 0x80))
+ neg = 1;
+ else
+ neg = 0;
+ utmp = 0;
+ for (i = 0; i < len; i++) {
+ utmp <<= 8;
+ if (neg)
+ utmp |= cont[i] ^ 0xff;
+ else
+ utmp |= cont[i];
+ }
+ ltmp = (long)utmp;
+ if (neg) {
+ ltmp++;
+ ltmp = -ltmp;
+ }
+ if (ltmp == it->size) {
+ ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+ return 0;
+ }
+ memcpy(cp, <mp, sizeof(long));
+ return 1;