Skip to content

Commit 8e62284

Browse files
committed
Fix out of bound access in src_linear
Fix #208 about out of bount access in linear resampler. Also migrates to count the sumber of frames instead of the number of samples and remove some redundant member of the private state. Signed-off-by: Lionel Koenig Gélas <[email protected]>
1 parent e7c6d89 commit 8e62284

File tree

1 file changed

+40
-47
lines changed

1 file changed

+40
-47
lines changed

src/src_linear.c

Lines changed: 40 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ static void linear_close (SRC_STATE *state) ;
3232

3333
typedef struct
3434
{ int linear_magic_marker ;
35-
bool dirty ;
36-
long in_count, in_used ;
37-
long out_count, out_gen ;
35+
bool initialized ;
3836
float *last_value ;
3937
} LINEAR_DATA ;
4038

@@ -54,7 +52,6 @@ static SRC_ERROR
5452
linear_vari_process (SRC_STATE *state, SRC_DATA *data)
5553
{ LINEAR_DATA *priv ;
5654
double src_ratio, input_index, rem ;
57-
int ch ;
5855

5956
if (data->input_frames <= 0)
6057
return SRC_ERR_NO_ERROR ;
@@ -64,16 +61,14 @@ linear_vari_process (SRC_STATE *state, SRC_DATA *data)
6461

6562
priv = (LINEAR_DATA*) state->private_data ;
6663

67-
if (!priv->dirty)
64+
if (!priv->initialized)
6865
{ /* If we have just been reset, set the last_value data. */
69-
for (ch = 0 ; ch < state->channels ; ch++)
66+
for (int ch = 0 ; ch < state->channels ; ch++)
7067
priv->last_value [ch] = data->data_in [ch] ;
71-
priv->dirty = true ;
68+
priv->initialized = true ;
7269
} ;
7370

74-
priv->in_count = data->input_frames * state->channels ;
75-
priv->out_count = data->output_frames * state->channels ;
76-
priv->in_used = priv->out_gen = 0 ;
71+
data->input_frames_used = data->output_frames_gen = 0 ;
7772

7873
src_ratio = state->last_ratio ;
7974

@@ -83,72 +78,70 @@ linear_vari_process (SRC_STATE *state, SRC_DATA *data)
8378
input_index = state->last_position ;
8479

8580
/* Calculate samples before first sample in input array. */
86-
while (input_index < 1.0 && priv->out_gen < priv->out_count)
81+
float* current_out = data->data_out;
82+
while (input_index < 1.0 && data->output_frames_gen < data->output_frames)
8783
{
88-
if (priv->in_used + state->channels * (1.0 + input_index) >= priv->in_count)
89-
break ;
84+
if (data->output_frames > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
85+
src_ratio = state->last_ratio + data->output_frames_gen * (data->src_ratio - state->last_ratio) / data->output_frames ;
9086

91-
if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
92-
src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ;
93-
94-
for (ch = 0 ; ch < state->channels ; ch++)
95-
{ data->data_out [priv->out_gen] = (float) (priv->last_value [ch] + input_index *
87+
for (int ch = 0 ; ch < state->channels ; ch++)
88+
{ *current_out++ = (float) (priv->last_value [ch] + input_index *
9689
((double) data->data_in [ch] - priv->last_value [ch])) ;
97-
priv->out_gen ++ ;
9890
} ;
91+
data->output_frames_gen ++ ;
9992

10093
/* Figure out the next index. */
10194
input_index += 1.0 / src_ratio ;
10295
} ;
10396

10497
rem = fmod_one (input_index) ;
105-
priv->in_used += state->channels * psf_lrint (input_index - rem) ;
98+
data->input_frames_used += psf_lrint (input_index - rem) ;
10699
input_index = rem ;
107100

108101
/* Main processing loop. */
109-
while (priv->out_gen < priv->out_count && priv->in_used + state->channels * input_index < priv->in_count)
110-
{
111-
if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
112-
src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ;
113-
114102
#if SRC_DEBUG
115-
if (priv->in_used < state->channels && input_index < 1.0)
116-
{ printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", priv->in_used, state->channels, input_index) ;
117-
exit (1) ;
118-
} ;
103+
assert(data->output_frames_gen >= data->output_frames || data->input_frames_used > 0);
119104
#endif
105+
while (data->output_frames_gen < data->output_frames && data->input_frames_used + input_index < data->input_frames)
106+
{
107+
if (data->output_frames > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
108+
src_ratio = state->last_ratio + data->output_frames_gen * (data->src_ratio - state->last_ratio) / data->output_frames ;
120109

121-
for (ch = 0 ; ch < state->channels ; ch++)
122-
{ data->data_out [priv->out_gen] = (float) (data->data_in [priv->in_used - state->channels + ch] + input_index *
123-
((double) data->data_in [priv->in_used + ch] - data->data_in [priv->in_used - state->channels + ch])) ;
124-
priv->out_gen ++ ;
125-
} ;
110+
const float* current_in = data->data_in + data->input_frames_used * state->channels;
111+
const float* prev_in = current_in - state->channels;
112+
for (int ch = 0 ; ch < state->channels ; ch++)
113+
{
114+
*current_out++ = (float) (prev_in[ch] + input_index *
115+
((double) current_in[ch] - prev_in[ch])) ;
116+
}
117+
data->output_frames_gen ++ ;
126118

127119
/* Figure out the next index. */
128120
input_index += 1.0 / src_ratio ;
129121
rem = fmod_one (input_index) ;
130122

131-
priv->in_used += state->channels * psf_lrint (input_index - rem) ;
123+
const int num_frame_used = psf_lrint (input_index - rem);
124+
data->input_frames_used += num_frame_used ;
132125
input_index = rem ;
133-
} ;
126+
}
134127

135-
if (priv->in_used > priv->in_count)
136-
{ input_index += (priv->in_used - priv->in_count) / state->channels ;
137-
priv->in_used = priv->in_count ;
138-
} ;
128+
if (data->input_frames_used > data->input_frames)
129+
{
130+
input_index += (data->input_frames_used - data->input_frames) ;
131+
data->input_frames_used = data->input_frames ;
132+
}
139133

140134
state->last_position = input_index ;
141135

142-
if (priv->in_used > 0)
143-
for (ch = 0 ; ch < state->channels ; ch++)
144-
priv->last_value [ch] = data->data_in [priv->in_used - state->channels + ch] ;
136+
if (data->input_frames_used > 0) {
137+
const float *last_value = data->data_in + (data->input_frames_used - 1) * state->channels;
138+
for (int ch = 0 ; ch < state->channels ; ch++)
139+
priv->last_value [ch] = last_value[ch];
140+
}
145141

146142
/* Save current ratio rather then target ratio. */
147143
state->last_ratio = src_ratio ;
148144

149-
data->input_frames_used = priv->in_used / state->channels ;
150-
data->output_frames_gen = priv->out_gen / state->channels ;
151-
152145
return SRC_ERR_NO_ERROR ;
153146
} /* linear_vari_process */
154147

@@ -237,7 +230,7 @@ linear_reset (SRC_STATE *state)
237230
if (priv == NULL)
238231
return ;
239232

240-
priv->dirty = false ;
233+
priv->initialized = false ;
241234
memset (priv->last_value, 0, sizeof (priv->last_value [0]) * state->channels) ;
242235

243236
return ;

0 commit comments

Comments
 (0)