mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Fix possible internal overflow in numeric division.
div_var_fast() postpones propagating carries in the same way as mul_var(),
so it has the same corner-case overflow risk we fixed in 246693e5ae,
namely that the size of the carries has to be accounted for when setting
the threshold for executing a carry propagation step.  We've not devised
a test case illustrating the brokenness, but the required fix seems clear
enough.  Like the previous fix, back-patch to all active branches.
Dean Rasheed
			
			
This commit is contained in:
		@@ -5311,8 +5311,14 @@ div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result,
 | 
				
			|||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * maxdiv tracks the maximum possible absolute value of any div[] entry;
 | 
						 * maxdiv tracks the maximum possible absolute value of any div[] entry;
 | 
				
			||||||
	 * when this threatens to exceed INT_MAX, we take the time to propagate
 | 
						 * when this threatens to exceed INT_MAX, we take the time to propagate
 | 
				
			||||||
	 * carries.  To avoid overflow in maxdiv itself, it actually represents
 | 
						 * carries.  Furthermore, we need to ensure that overflow doesn't occur
 | 
				
			||||||
	 * the max possible abs. value divided by NBASE-1.
 | 
						 * during the carry propagation passes either.  The carry values may have
 | 
				
			||||||
 | 
						 * an absolute value as high as INT_MAX/NBASE + 1, so really we must
 | 
				
			||||||
 | 
						 * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * To avoid overflow in maxdiv itself, it represents the max absolute
 | 
				
			||||||
 | 
						 * value divided by NBASE-1, ie, at the top of the loop it is known that
 | 
				
			||||||
 | 
						 * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	maxdiv = 1;
 | 
						maxdiv = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -5338,7 +5344,7 @@ div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result,
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			/* Do we need to normalize now? */
 | 
								/* Do we need to normalize now? */
 | 
				
			||||||
			maxdiv += Abs(qdigit);
 | 
								maxdiv += Abs(qdigit);
 | 
				
			||||||
			if (maxdiv > INT_MAX / (NBASE - 1))
 | 
								if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				/* Yes, do it */
 | 
									/* Yes, do it */
 | 
				
			||||||
				carry = 0;
 | 
									carry = 0;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user