3
3
4
4
using System ;
5
5
using System . Collections . Generic ;
6
+ using System . Diagnostics ;
6
7
using System . Diagnostics . Contracts ;
7
8
using System . Globalization ;
8
9
using Microsoft . Extensions . Primitives ;
@@ -200,6 +201,33 @@ internal static int GetNextNonEmptyOrWhitespaceIndex(
200
201
return current ;
201
202
}
202
203
204
+ private static int AdvanceCacheDirectiveIndex ( int current , string headerValue )
205
+ {
206
+ // Skip until the next potential name
207
+ current += HttpRuleParser . GetWhitespaceLength ( headerValue , current ) ;
208
+
209
+ // Skip the value if present
210
+ if ( current < headerValue . Length && headerValue [ current ] == '=' )
211
+ {
212
+ current ++ ; // skip '='
213
+ current += NameValueHeaderValue . GetValueLength ( headerValue , current ) ;
214
+ }
215
+
216
+ // Find the next delimiter
217
+ current = headerValue . IndexOf ( ',' , current ) ;
218
+
219
+ if ( current == - 1 )
220
+ {
221
+ // If no delimiter found, skip to the end
222
+ return headerValue . Length ;
223
+ }
224
+
225
+ current ++ ; // skip ','
226
+ current += HttpRuleParser . GetWhitespaceLength ( headerValue , current ) ;
227
+
228
+ return current ;
229
+ }
230
+
203
231
/// <summary>
204
232
/// Try to find a target header value among the set of given header values and parse it as a
205
233
/// <see cref="TimeSpan"/>.
@@ -237,6 +265,7 @@ public static bool TryParseSeconds(StringValues headerValues, string targetValue
237
265
while ( current < headerValues [ i ] . Length )
238
266
{
239
267
long seconds ;
268
+ var initial = current ;
240
269
var tokenLength = HttpRuleParser . GetTokenLength ( headerValues [ i ] , current ) ;
241
270
if ( tokenLength == targetValue . Length
242
271
&& string . Compare ( headerValues [ i ] , current , targetValue , 0 , tokenLength , StringComparison . OrdinalIgnoreCase ) == 0
@@ -246,26 +275,15 @@ public static bool TryParseSeconds(StringValues headerValues, string targetValue
246
275
value = TimeSpan . FromSeconds ( seconds ) ;
247
276
return true ;
248
277
}
249
- else
250
- {
251
- // Skip until the next potential name
252
- current += tokenLength ;
253
- current += HttpRuleParser . GetWhitespaceLength ( headerValues [ i ] , current ) ;
254
278
255
- // Skip the value if present
256
- if ( current < headerValues [ i ] . Length && headerValues [ i ] [ current ] == '=' )
257
- {
258
- current ++ ; // skip '='
259
- current += NameValueHeaderValue . GetValueLength ( headerValues [ i ] , current ) ;
260
- current += HttpRuleParser . GetWhitespaceLength ( headerValues [ i ] , current ) ;
261
- }
279
+ current = AdvanceCacheDirectiveIndex ( current + tokenLength , headerValues [ i ] ) ;
262
280
263
- // Skip the delimiter
264
- if ( current < headerValues [ i ] . Length && headerValues [ i ] [ current ] == ',' )
265
- {
266
- current ++ ; // skip ','
267
- current += HttpRuleParser . GetWhitespaceLength ( headerValues [ i ] , current ) ;
268
- }
281
+ // Ensure index was advanced
282
+ if ( current <= initial )
283
+ {
284
+ Debug . Assert ( false , $ "Index ' { nameof ( current ) } ' not advanced, this is a bug." ) ;
285
+ value = null ;
286
+ return false ;
269
287
}
270
288
}
271
289
}
@@ -293,41 +311,30 @@ public static bool ContainsCacheDirective(StringValues cacheControlDirectives, s
293
311
return false ;
294
312
}
295
313
296
-
297
314
for ( var i = 0 ; i < cacheControlDirectives . Count ; i ++ )
298
315
{
299
316
// Trim leading white space
300
317
var current = HttpRuleParser . GetWhitespaceLength ( cacheControlDirectives [ i ] , 0 ) ;
301
318
302
319
while ( current < cacheControlDirectives [ i ] . Length )
303
320
{
321
+ var initial = current ;
322
+
304
323
var tokenLength = HttpRuleParser . GetTokenLength ( cacheControlDirectives [ i ] , current ) ;
305
324
if ( tokenLength == targetDirectives . Length
306
325
&& string . Compare ( cacheControlDirectives [ i ] , current , targetDirectives , 0 , tokenLength , StringComparison . OrdinalIgnoreCase ) == 0 )
307
326
{
308
327
// Token matches target value
309
328
return true ;
310
329
}
311
- else
312
- {
313
- // Skip until the next potential name
314
- current += tokenLength ;
315
- current += HttpRuleParser . GetWhitespaceLength ( cacheControlDirectives [ i ] , current ) ;
316
330
317
- // Skip the value if present
318
- if ( current < cacheControlDirectives [ i ] . Length && cacheControlDirectives [ i ] [ current ] == '=' )
319
- {
320
- current ++ ; // skip '='
321
- current += NameValueHeaderValue . GetValueLength ( cacheControlDirectives [ i ] , current ) ;
322
- current += HttpRuleParser . GetWhitespaceLength ( cacheControlDirectives [ i ] , current ) ;
323
- }
331
+ current = AdvanceCacheDirectiveIndex ( current + tokenLength , cacheControlDirectives [ i ] ) ;
324
332
325
- // Skip the delimiter
326
- if ( current < cacheControlDirectives [ i ] . Length && cacheControlDirectives [ i ] [ current ] == ',' )
327
- {
328
- current ++ ; // skip ','
329
- current += HttpRuleParser . GetWhitespaceLength ( cacheControlDirectives [ i ] , current ) ;
330
- }
333
+ // Ensure index was advanced
334
+ if ( current <= initial )
335
+ {
336
+ Debug . Assert ( false , $ "Index '{ nameof ( current ) } ' not advanced, this is a bug.") ;
337
+ return false ;
331
338
}
332
339
}
333
340
}
0 commit comments