@@ -44,6 +44,17 @@ bool is_power_of_two(size_t n) {
4444 return n > 0 && (n & (n - 1 )) == 0 ;
4545}
4646
47+ bool add_overflows_size (size_t a, size_t b) {
48+ return a > std::numeric_limits<size_t >::max () - b;
49+ }
50+
51+ bool mul_overflows_size (size_t a, size_t b) {
52+ if (a == 0 || b == 0 ) {
53+ return false ;
54+ }
55+ return a > std::numeric_limits<size_t >::max () / b;
56+ }
57+
4758int reflect_index (long long i, size_t n) {
4859 if (n <= 1 ) return 0 ;
4960 const long long period = static_cast <long long >(2 * n - 2 );
@@ -134,46 +145,57 @@ bfft_status bfft_stft_plan_create(size_t n, size_t n_fft, size_t hop_length, con
134145 if (hop_length == 0 || hop_length > n_fft || (n_fft % hop_length) != 0 ) return BFFT_ERROR_INVALID_ARGUMENT ;
135146 if ((n % hop_length) != 0 ) return BFFT_ERROR_INVALID_ARGUMENT ;
136147 if (transform != BFFT_STFT_RFFT && transform != BFFT_STFT_ODFT ) return BFFT_ERROR_INVALID_ARGUMENT ;
148+ if (n > static_cast <size_t >(std::numeric_limits<long long >::max ())) return BFFT_ERROR_INVALID_ARGUMENT ;
149+ if (n_fft > (static_cast <size_t >(std::numeric_limits<long long >::max ()) + 2 ) / 2 ) return BFFT_ERROR_INVALID_ARGUMENT ;
150+ if (n_fft > std::numeric_limits<int >::max ()) return BFFT_ERROR_INVALID_ARGUMENT ;
151+ if (add_overflows_size (n, n_fft - 1 )) return BFFT_ERROR_INVALID_ARGUMENT ;
152+ if (mul_overflows_size (n / hop_length, n_fft / 2 + 1 )) return BFFT_ERROR_INVALID_ARGUMENT ;
137153
138- std::unique_ptr<bfft_stft_plan> p (new (std::nothrow) bfft_stft_plan ());
139- if (!p) return BFFT_ERROR_ALLOCATION ;
140- p->n = n;
141- p->n_fft = n_fft;
142- p->hop = hop_length;
143- p->segments = n / hop_length;
144- p->transform = transform;
145- p->window .resize (n_fft);
146- if (window) {
147- for (size_t i = 0 ; i < n_fft; ++i) {
148- if (!std::isfinite (window[i])) return BFFT_ERROR_INVALID_ARGUMENT ;
149- p->window [i] = window[i];
154+ try {
155+ std::unique_ptr<bfft_stft_plan> p (new (std::nothrow) bfft_stft_plan ());
156+ if (!p) return BFFT_ERROR_ALLOCATION ;
157+ p->n = n;
158+ p->n_fft = n_fft;
159+ p->hop = hop_length;
160+ p->segments = n / hop_length;
161+ p->transform = transform;
162+ p->window .resize (n_fft);
163+ if (window) {
164+ for (size_t i = 0 ; i < n_fft; ++i) {
165+ if (!std::isfinite (window[i])) return BFFT_ERROR_INVALID_ARGUMENT ;
166+ p->window [i] = window[i];
167+ }
168+ } else {
169+ bfft_status st = bfft_stft_hann_window (n_fft, p->window .data ());
170+ if (st != BFFT_OK ) return st;
150171 }
151- } else {
152- bfft_status st = bfft_stft_hann_window (n_fft, p->window .data ());
153- if (st != BFFT_OK ) return st;
154- }
155- p->analysis .resize (n_fft);
156- ifftshift_copy (p->window , p->analysis );
157- if (!synthesis_window (p->window , hop_length, p->synthesis )) return BFFT_ERROR_INVALID_ARGUMENT ;
172+ p->analysis .resize (n_fft);
173+ ifftshift_copy (p->window , p->analysis );
174+ if (!synthesis_window (p->window , hop_length, p->synthesis )) return BFFT_ERROR_INVALID_ARGUMENT ;
158175
159- if (transform == BFFT_STFT_RFFT ) {
160- bfft_status st = bfft_plan_create (n_fft, &p->rfft );
161- if (st != BFFT_OK ) return st;
162- p->bins = bfft_plan_bins (p->rfft );
163- p->work .resize (bfft_plan_work_size (p->rfft ));
164- p->scratch .resize (bfft_plan_native_scratch_size (p->rfft ));
165- } else {
166- bfft_status st = bodft_plan_create (n_fft, &p->odft );
167- if (st != BFFT_OK ) return st;
168- p->bins = bodft_plan_bins (p->odft );
176+ if (transform == BFFT_STFT_RFFT ) {
177+ bfft_status st = bfft_plan_create (n_fft, &p->rfft );
178+ if (st != BFFT_OK ) return st;
179+ p->bins = bfft_plan_bins (p->rfft );
180+ p->work .resize (bfft_plan_work_size (p->rfft ));
181+ p->scratch .resize (bfft_plan_native_scratch_size (p->rfft ));
182+ } else {
183+ bfft_status st = bodft_plan_create (n_fft, &p->odft );
184+ if (st != BFFT_OK ) return st;
185+ p->bins = bodft_plan_bins (p->odft );
186+ }
187+ p->buffer .assign (n_fft - hop_length, 0.0 );
188+ p->xp .resize (n + n_fft - 1 );
189+ p->segment .resize (n_fft);
190+ p->frame .resize (n_fft);
191+ p->processed .resize (n_fft);
192+ p->tmp_bins .resize (p->bins );
193+ *out_plan = p.release ();
194+ } catch (const std::bad_alloc&) {
195+ return BFFT_ERROR_ALLOCATION ;
196+ } catch (...) {
197+ return BFFT_ERROR_INTERNAL ;
169198 }
170- p->buffer .assign (n_fft - hop_length, 0.0 );
171- p->xp .resize (n + n_fft - 1 );
172- p->segment .resize (n_fft);
173- p->frame .resize (n_fft);
174- p->processed .resize (n_fft);
175- p->tmp_bins .resize (p->bins );
176- *out_plan = p.release ();
177199 return BFFT_OK ;
178200}
179201
0 commit comments