@@ -116,14 +116,28 @@ func (pa *priorityAssigner) initialOFPriority(p types.Priority) uint16 {
116116 tierOffsetBase = tierOffsetBaselineTier
117117 priorityOffsetBase = priorityOffsetBaselineTier
118118 }
119- tierOffset := tierOffsetBase * uint16 (p .TierPriority )
120- priorityOffset := uint16 (p .PolicyPriority * priorityOffsetBase )
121- offSet := tierOffset + priorityOffset + uint16 (p .RulePriority )
122- // Cannot return a negative OF priority.
123- if pa .policyTopPriority - pa .policyBottomPriority < offSet {
119+ // Use uint32 to prevent arithmetic overflow during calculation
120+ tierOffset := uint32 (tierOffsetBase ) * uint32 (p .TierPriority )
121+ priorityOffset := uint32 (p .PolicyPriority * priorityOffsetBase )
122+ offSet := tierOffset + priorityOffset + uint32 (p .RulePriority )
123+
124+ // Check if the calculated offset exceeds the available priority range
125+ availableRange := uint32 (pa .policyTopPriority ) - uint32 (pa .policyBottomPriority )
126+ if availableRange < offSet {
124127 return pa .policyBottomPriority
125128 }
126- return pa .policyTopPriority - offSet
129+ // Safe to cast offSet to uint16: the preceding if statement guarantees that
130+ // offSet <= availableRange <= (policyTopPriority - policyBottomPriority) <= math.MaxUint16
131+ return pa .policyTopPriority - uint16 (offSet )
132+ }
133+
134+ // findGap calculates the gap between upperBound and lowerBound with uint16 underflow protection.
135+ // Returns the gap and whether there is any space available.
136+ func findGap (upperBound , lowerBound uint16 ) (gap uint16 , hasSpace bool ) {
137+ if upperBound <= lowerBound {
138+ return 0 , false
139+ }
140+ return upperBound - lowerBound - 1 , true
127141}
128142
129143// updatePriorityAssignment updates all the local maps to correlate input ofPriority and Priority.
@@ -154,12 +168,26 @@ func (pa *priorityAssigner) findReassignBoundaries(lowerBound, upperBound uint16
154168 costMap := map [int ]* reassignCost {}
155169 reassignBoundLow , reassignBoundHigh := lowerBound , upperBound
156170 costSiftDown , costSiftUp , emptiedSlotsLow , emptiedSlotsHigh := 0 , 0 , 0 , 0
171+ // Search for empty slots below lowerBound, but don't go below policyBottomPriority
157172 for reassignBoundLow >= pa .policyBottomPriority && emptiedSlotsLow < target {
158173 if _ , exists := pa .ofPriorityMap [reassignBoundLow ]; exists {
159174 costSiftDown ++
160175 } else {
161176 emptiedSlotsLow ++
162- costMap [emptiedSlotsLow ] = & reassignCost {reassignBoundLow , upperBound - 1 , costSiftDown }
177+ // When upperBound == lowerBound, use upperBound directly to create a valid single-slot range
178+ // When upperBound > lowerBound, use upperBound - 1 to avoid overlapping with the gap
179+ upperBoundForCost := upperBound
180+ if upperBound > lowerBound {
181+ upperBoundForCost = upperBound - 1
182+ }
183+ // Special case: when we're at the boundary itself, include it in the range
184+ if reassignBoundLow == lowerBound && upperBound == lowerBound {
185+ upperBoundForCost = upperBound // Include the boundary slot
186+ }
187+ // Only create cost map entry if it results in a valid range
188+ if reassignBoundLow <= upperBoundForCost {
189+ costMap [emptiedSlotsLow ] = & reassignCost {reassignBoundLow , upperBoundForCost , costSiftDown }
190+ }
163191 }
164192 reassignBoundLow --
165193 }
@@ -178,7 +206,12 @@ func (pa *priorityAssigner) findReassignBoundaries(lowerBound, upperBound uint16
178206 c .cost = costSiftDown + costSiftUp
179207 c .upperBound = reassignBoundHigh
180208 } else if mapIndex == 0 {
181- costMap [mapIndex ] = & reassignCost {lowerBound + 1 , reassignBoundHigh , costSiftUp }
209+ // When upperBound == lowerBound, start from lowerBound itself, not lowerBound + 1
210+ startBound := lowerBound + 1
211+ if upperBound == lowerBound {
212+ startBound = lowerBound // Include the boundary slot in the reassignment range
213+ }
214+ costMap [mapIndex ] = & reassignCost {startBound , reassignBoundHigh , costSiftUp }
182215 }
183216 }
184217 reassignBoundHigh ++
@@ -187,7 +220,9 @@ func (pa *priorityAssigner) findReassignBoundaries(lowerBound, upperBound uint16
187220 for i := target ; i >= 0 ; i -- {
188221 if cost , exists := costMap [i ]; exists && cost .cost < minCost {
189222 // make sure that the reassign range adds up to the number of all Priorities to be registered.
190- if int (cost .upperBound - cost .lowerBound )+ 1 == numNewPriorities + cost .cost {
223+ rangeSize := int (cost .upperBound - cost .lowerBound ) + 1
224+ requiredSize := numNewPriorities + cost .cost
225+ if rangeSize == requiredSize {
191226 minCost = cost .cost
192227 minCostIndex = i
193228 }
@@ -205,20 +240,29 @@ func (pa *priorityAssigner) findReassignBoundaries(lowerBound, upperBound uint16
205240// map of updates, which is passed to it as parameter.
206241func (pa * priorityAssigner ) reassignBoundaryPriorities (lowerBound , upperBound uint16 , prioritiesToRegister types.ByPriority ,
207242 updates map [types.Priority ]* priorityUpdate ) error {
208- numNewPriorities , gap := len (prioritiesToRegister ), int (upperBound - lowerBound - 1 )
243+ numNewPriorities := len (prioritiesToRegister )
244+ gapUint16 , hasSpace := findGap (upperBound , lowerBound )
245+ var gap int
246+ if hasSpace {
247+ gap = int (gapUint16 )
248+ } else {
249+ gap = 0 // No available slots when upperBound <= lowerBound
250+ }
209251 low , high , err := pa .findReassignBoundaries (lowerBound , upperBound , numNewPriorities , gap )
210252 if err != nil {
211253 return err
212254 }
213255 // siftedPrioritiesLow and siftedPrioritiesHigh keep track of Priorities that need to be reassigned,
214- // below the lowerBound and above the upperBound respectively.
256+ // below the lowerBound and above the upperBound respectively. Note that we do not include the priority
257+ // currently assigned to policyBottomPriority since it cannot be sifted down further, and vice versa
258+ // for policyTopPriority.
215259 var siftedPrioritiesLow , siftedPrioritiesHigh types.ByPriority
216- for i := low ; i <= lowerBound ; i ++ {
260+ for i := low ; i <= lowerBound && i != pa . policyBottomPriority ; i ++ {
217261 if p , exists := pa .ofPriorityMap [i ]; exists {
218262 siftedPrioritiesLow = append (siftedPrioritiesLow , p )
219263 }
220264 }
221- for i := upperBound ; i <= high ; i ++ {
265+ for i := upperBound ; i <= high && i != pa . policyTopPriority ; i ++ {
222266 if p , exists := pa .ofPriorityMap [i ]; exists {
223267 siftedPrioritiesHigh = append (siftedPrioritiesHigh , p )
224268 }
@@ -236,7 +280,12 @@ func (pa *priorityAssigner) reassignBoundaryPriorities(lowerBound, upperBound ui
236280 }
237281 // assign ofPriorities by the order of siftedPrioritiesLow, prioritiesToRegister and siftedPrioritiesHigh.
238282 for i , p := range allPriorities {
239- pa .updatePriorityAssignment (low + uint16 (i ), p )
283+ // Protect against overflow when low + i > 65535
284+ ofPriority := uint64 (low ) + uint64 (i )
285+ if ofPriority > math .MaxUint16 {
286+ return fmt .Errorf ("priority assignment overflow: low=%d + i=%d exceeds uint16 range" , low , i )
287+ }
288+ pa .updatePriorityAssignment (uint16 (ofPriority ), p )
240289 }
241290 // record the ofPriorities of the reassigned Priorities after the reassignment.
242291 for _ , p := range reassignedPriorities {
@@ -273,8 +322,13 @@ func (pa *priorityAssigner) registerPriorities(priorities []types.Priority) (map
273322 klog .V (2 ).Infof ("%v new priorities need to be registered" , numPriorityToRegister )
274323 if numPriorityToRegister == 0 {
275324 return nil , nil , nil
276- } else if uint16 (numPriorityToRegister + len (pa .sortedPriorities )) > pa .policyTopPriority - pa .policyBottomPriority + 1 {
277- return nil , nil , fmt .Errorf ("number of priorities to be registered is greater than available openflow priorities" )
325+ } else {
326+ // Check for overflow before casting to uint16
327+ totalPriorities := numPriorityToRegister + len (pa .sortedPriorities )
328+ availableRange := uint32 (pa .policyTopPriority ) - uint32 (pa .policyBottomPriority ) + 1
329+ if uint32 (totalPriorities ) > availableRange {
330+ return nil , nil , fmt .Errorf ("number of priorities to be registered (%d) is greater than available openflow priorities (%d)" , totalPriorities , availableRange )
331+ }
278332 }
279333 sort .Sort (types .ByPriority (prioritiesToRegister ))
280334 var consecutivePriorities [][]types.Priority
@@ -340,32 +394,51 @@ func (pa *priorityAssigner) insertConsecutivePriorities(priorities types.ByPrior
340394 // set upperBound to the ofPriority of the registered Priority that is immediately higher than the inserting Priorities.
341395 upperBound = pa.priorityMap [pa.sortedPriorities [insertionIdx ]]
342396 }
343- // not enough space to insert Priorities.
344- if upperBound - lowerBound - 1 < uint16 (numPriorities ) {
397+ gap , hasSpace := findGap (upperBound , lowerBound )
398+ // not enough space currently to insert Priorities.
399+ if ! hasSpace || gap < uint16 (numPriorities ) {
345400 return pa .reassignBoundaryPriorities (lowerBound , upperBound , priorities , updates )
346401 }
347402 switch {
348403 // ofPriorities provided by the heuristic function are good.
349404 case insertionPointLow > lowerBound && insertionPointHigh < upperBound :
350405 break
351- // ofPriorities returned by the heuristic function overlap with existing Priorities/ are out of place.
406+ // ofPriorities returned by the heuristic function are out of place/overlap with existing Priorities .
352407 // If the Priorities to be registered overlap with lower Priorities/are lower than the lower Priorities,
353408 // and the gap between lowerBound and upperBound for insertion is large, then we insert these Priorities
354- // above the lowerBound, offsetted by a constant zoneOffset. Vice versa for the other way around .
409+ // above the lowerBound, offsetted by a constant zoneOffset, and vice versa .
355410 // 5 is chosen as the zoneOffset here since it gives some buffer in case Priorities are again created
356411 // in between those zones, while in the meantime keeps priority assignments compact.
357- case upperBound - lowerBound - 1 >= uint16 (numPriorities )+ 2 * zoneOffset :
412+ case gap >= uint16 (numPriorities )+ 2 * zoneOffset :
358413 if insertionPointLow <= lowerBound {
359- insertionPointLow = lowerBound + zoneOffset + 1
414+ // Protect against overflow: lowerBound + zoneOffset + 1
415+ if uint32 (lowerBound )+ uint32 (zoneOffset )+ 1 > math .MaxUint16 {
416+ insertionPointLow = math .MaxUint16 - uint16 (numPriorities ) + 1
417+ } else {
418+ insertionPointLow = lowerBound + zoneOffset + 1
419+ }
360420 } else {
361- insertionPointLow = upperBound - zoneOffset - uint16 (len (priorities ))
421+ // Protect against underflow: upperBound - zoneOffset - uint16(len(priorities))
422+ requiredSpace := uint32 (zoneOffset ) + uint32 (len (priorities ))
423+ if uint32 (upperBound ) < requiredSpace {
424+ insertionPointLow = pa .policyBottomPriority
425+ } else {
426+ insertionPointLow = upperBound - zoneOffset - uint16 (len (priorities ))
427+ }
362428 }
363429 // when the window between upper/lowerBound is small, simply put the Priorities in the middle of the window.
364430 default :
365- insertionPointLow = lowerBound + (upperBound - lowerBound - uint16 (numPriorities ))/ 2 + 1
431+ // gap is guaranteed >= numPriorities by the condition check above
432+ // So gap - uint16(numPriorities) will not underflow
433+ insertionPointLow = lowerBound + (gap - uint16 (numPriorities ))/ 2 + 1
366434 }
367435 for i := 0 ; i < len (priorities ); i ++ {
368- pa .updatePriorityAssignment (insertionPointLow + uint16 (i ), priorities [i ])
436+ // Protect against overflow: insertionPointLow + uint16(i)
437+ ofPriority := uint32 (insertionPointLow ) + uint32 (i )
438+ if ofPriority > math .MaxUint16 {
439+ return fmt .Errorf ("priority assignment overflow: insertionPoint=%d + i=%d exceeds uint16 range" , insertionPointLow , i )
440+ }
441+ pa .updatePriorityAssignment (uint16 (ofPriority ), priorities [i ])
369442 }
370443 return nil
371444}
0 commit comments