@@ -6140,8 +6140,10 @@ int sp_leading_bit(const sp_int* a)
61406140int sp_set_bit(sp_int* a, int i)
61416141{
61426142 int err = MP_OKAY;
6143- /* Get index of word to set. */
6144- sp_size_t w = (sp_size_t)(i >> SP_WORD_SHIFT);
6143+ /* Compute word index in full int width so that bit indices large enough
6144+ * to make the word index overflow sp_size_t are caught by the bounds
6145+ * check below rather than wrapping. */
6146+ int wi = (i < 0) ? 0 : (i >> SP_WORD_SHIFT);
61456147
61466148#if SP_INT_DIGITS < (65536 / SP_WORD_SIZEOF)
61476149 /* Check bit index isn't bigger than maximum allowed. */
@@ -6151,10 +6153,11 @@ int sp_set_bit(sp_int* a, int i)
61516153 else
61526154#endif
61536155 /* Check for valid number and space for bit. */
6154- if ((a == NULL) || (i < 0) || (w >= a->size)) {
6156+ if ((a == NULL) || (i < 0) || (wi >= (int) a->size)) {
61556157 err = MP_VAL;
61566158 }
61576159 if (err == MP_OKAY) {
6160+ sp_size_t w = (sp_size_t)wi;
61586161 /* Amount to shift up to set bit in word. */
61596162 unsigned int s = (unsigned int)(i & (SP_WORD_SIZE - 1));
61606163 unsigned int j;
@@ -8627,15 +8630,16 @@ void sp_rshd(sp_int* a, int c)
86278630{
86288631 /* Do shift if we have an SP int. */
86298632 if ((a != NULL) && (c > 0)) {
8630- /* Make zero if shift removes all digits. */
8631- if ((sp_size_t)c >= a->used) {
8633+ /* Compare c in int width to avoid narrowing to sp_size_t (which can
8634+ * be word16) before the bounds check. */
8635+ if (c >= (int)a->used) {
86328636 _sp_zero(a);
86338637 }
86348638 else {
86358639 sp_size_t i;
86368640
86378641 /* Update used digits count. */
8638- a->used = (sp_size_t)(a->used - c);
8642+ a->used = (sp_size_t)((int) a->used - c);
86398643 /* Move digits down. */
86408644 for (i = 0; i < a->used; i++, c++) {
86418645 a->dp[i] = a->dp[c];
@@ -8657,21 +8661,23 @@ void sp_rshd(sp_int* a, int c)
86578661int sp_rshb(const sp_int* a, int n, sp_int* r)
86588662{
86598663 int err = MP_OKAY;
8660- /* Number of digits to shift down. */
8661- sp_size_t i;
8664+ /* Compute the digit-shift count in full int width to avoid wrapping
8665+ * when n is large enough that the count would exceed sp_size_t range. */
8666+ int ni = (n < 0) ? 0 : (n >> SP_WORD_SHIFT);
86628667
86638668 if ((a == NULL) || (n < 0)) {
86648669 err = MP_VAL;
86658670 }
86668671 /* Handle case where shifting out all digits. */
8667- else if ((i = (sp_size_t)(n >> SP_WORD_SHIFT)) >= a->used) {
8672+ else if (ni > = (int) a->used) {
86688673 _sp_zero(r);
86698674 }
86708675 /* Change callers when more error cases returned. */
8671- else if ((err == MP_OKAY) && (a->used - i > r->size)) {
8676+ else if ((err == MP_OKAY) && ((int) a->used - ni > (int) r->size)) {
86728677 err = MP_VAL;
86738678 }
86748679 else if (err == MP_OKAY) {
8680+ sp_size_t i = (sp_size_t)ni;
86758681 sp_size_t j;
86768682
86778683 /* Number of bits to shift in digits. */
@@ -14920,16 +14926,25 @@ int sp_div_2d(const sp_int* a, int e, sp_int* r, sp_int* rem)
1492014926int sp_mod_2d(const sp_int* a, int e, sp_int* r)
1492114927{
1492214928 int err = MP_OKAY;
14923- sp_size_t digits = (sp_size_t)((e + SP_WORD_SIZE - 1) >> SP_WORD_SHIFT);
14929+ /* Compute digit count in full int width. Decompose to avoid signed
14930+ * overflow if e is near INT_MAX: (e + SP_WORD_SIZE - 1) >> SHIFT is
14931+ * equivalent to (e >> SHIFT) + (e has remainder ? 1 : 0). */
14932+ int digits_full = 0;
14933+ sp_size_t digits = 0;
1492414934
1492514935 if ((a == NULL) || (r == NULL) || (e < 0)) {
1492614936 err = MP_VAL;
1492714937 }
14928- if ((err == MP_OKAY) && (digits > r->size)) {
14929- err = MP_VAL;
14938+ if (err == MP_OKAY) {
14939+ digits_full = (e >> SP_WORD_SHIFT) +
14940+ (((e & (SP_WORD_SIZE - 1)) != 0) ? 1 : 0);
14941+ if (digits_full > (int)r->size) {
14942+ err = MP_VAL;
14943+ }
1493014944 }
1493114945
1493214946 if (err == MP_OKAY) {
14947+ digits = (sp_size_t)digits_full;
1493314948 /* Copy a into r if not same pointer. */
1493414949 if (a != r) {
1493514950 sp_size_t cnt = (a->used < digits) ? a->used : digits;
0 commit comments