shithub: opusfile

Download patch

ref: 8d153c572972830bbf71f98cef25c16a6ea733cc
parent: ec63ede671f9af57e1bde766586f923183ae99a0
author: Timothy B. Terriberry <tterribe@xiph.org>
date: Fri Apr 11 05:01:28 EDT 2025

Avoid rescanning invalid regions during file open.

If there is a large region of invalid data in the middle of the
 file, avoid scanning it repeatedly during chain boundary
 enumeration.
Because of the bisection, doing that would only be O(n*log(n)), not
 quadratic like op_get_last_page(), but still good to avoid.

--- a/src/opusfile.c
+++ b/src/opusfile.c
@@ -1189,6 +1189,7 @@
     /*We guard against garbage separating the last and first pages of two
        links below.*/
     while(_searched<end_searched){
+      opus_int64 boundary;
       opus_int32 next_bias;
       /*If we don't have a better estimate, use simple bisection.*/
       if(bisect==-1)bisect=_searched+(end_searched-_searched>>1);
@@ -1199,7 +1200,14 @@
       else end_gp=-1;
       ret=op_seek_helper(_of,bisect);
       if(OP_UNLIKELY(ret<0))return ret;
-      last=op_get_next_page(_of,&og,_sr[nsr-1].offset);
+      /*If there is a large region of invalid data in the middle of the file,
+         avoid scanning it repeatedly.
+        Because of the bisection, doing that would only be O(n*log(n)), not
+         quadratic like op_get_last_page(), but still good to avoid.*/
+      OP_ASSERT(end_searched<=_sr[nsr-1].search_start);
+      boundary=OP_MIN(_sr[nsr-1].offset,
+       OP_ADV_OFFSET(end_searched,OP_PAGE_SIZE_MAX-1));
+      last=op_get_next_page(_of,&og,boundary);
       if(OP_UNLIKELY(last<OP_FALSE))return (int)last;
       next_bias=0;
       if(last==OP_FALSE)end_searched=bisect;
--