~siretart/xine-lib/ubuntu

« back to all changes in this revision

Viewing changes to src/libffmpeg/libavcodec/eval.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2005-12-15 13:13:45 UTC
  • mfrom: (0.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051215131345-8n4osv1j7fy9c1s1
* SECURITY UPDATE: Fix arbitrary code execution with crafted PNG images in
  embedded ffmpeg copy.
* src/libffmpeg/libavcodec/utils.c, avcodec_default_get_buffer(): Apply
  upstream patch to fix buffer overflow on decoding of small PIX_FMT_PAL8
  PNG files.
* References:
  CVE-2005-4048
  http://mplayerhq.hu/pipermail/ffmpeg-devel/2005-November/005333.html
  http://www1.mplayerhq.hu/cgi-bin/cvsweb.cgi/ffmpeg/libavcodec/
  utils.c.diff?r1=1.161&r2=1.162&cvsroot=FFMpeg

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
#define M_PI 3.14159265358979323846
43
43
#endif
44
44
 
45
 
#define STACK_SIZE 100
46
 
 
47
45
typedef struct Parser{
48
 
    double stack[STACK_SIZE];
49
46
    int stack_index;
50
47
    char *s;
51
48
    double *const_value;
57
54
    void *opaque;
58
55
} Parser;
59
56
 
60
 
static void evalExpression(Parser *p);
61
 
 
62
 
static void push(Parser *p, double d){
63
 
    if(p->stack_index+1>= STACK_SIZE){
64
 
        av_log(NULL, AV_LOG_ERROR, "stack overflow in the parser\n");
65
 
        return;
66
 
    }
67
 
    p->stack[ p->stack_index++ ]= d;
68
 
//printf("push %f\n", d); fflush(stdout);
69
 
}
70
 
 
71
 
static double pop(Parser *p){
72
 
    if(p->stack_index<=0){
73
 
        av_log(NULL, AV_LOG_ERROR, "stack underflow in the parser\n");
74
 
        return NAN;
75
 
    }
76
 
//printf("pop\n"); fflush(stdout);
77
 
    return p->stack[ --p->stack_index ];
78
 
}
 
57
static double evalExpression(Parser *p);
79
58
 
80
59
static int strmatch(const char *s, const char *prefix){
81
60
    int i;
85
64
    return 1;
86
65
}
87
66
 
88
 
static void evalPrimary(Parser *p){
 
67
static double evalPrimary(Parser *p){
89
68
    double d, d2=NAN;
90
69
    char *next= p->s;
91
70
    int i;
93
72
    /* number */
94
73
    d= strtod(p->s, &next);
95
74
    if(next != p->s){
96
 
        push(p, d);
97
75
        p->s= next;
98
 
        return;
 
76
        return d;
99
77
    }
100
78
    
101
79
    /* named constants */
102
 
    for(i=0; p->const_name[i]; i++){
 
80
    for(i=0; p->const_name && p->const_name[i]; i++){
103
81
        if(strmatch(p->s, p->const_name[i])){
104
 
            push(p, p->const_value[i]);
105
82
            p->s+= strlen(p->const_name[i]);
106
 
            return;
 
83
            return p->const_value[i];
107
84
        }
108
85
    }
109
86
    
110
87
    p->s= strchr(p->s, '(');
111
88
    if(p->s==NULL){
112
89
        av_log(NULL, AV_LOG_ERROR, "Parser: missing ( in \"%s\"\n", next);
113
 
        return;
 
90
        return NAN;
114
91
    }
115
92
    p->s++; // "("
116
 
    evalExpression(p);
117
 
    d= pop(p);
 
93
    d= evalExpression(p);
118
94
    if(p->s[0]== ','){
119
95
        p->s++; // ","
120
 
        evalExpression(p);
121
 
        d2= pop(p);
 
96
        d2= evalExpression(p);
122
97
    }
123
98
    if(p->s[0] != ')'){
124
99
        av_log(NULL, AV_LOG_ERROR, "Parser: missing ) in \"%s\"\n", next);
125
 
        return;
 
100
        return NAN;
126
101
    }
127
102
    p->s++; // ")"
128
103
    
144
119
    else if( strmatch(next, "lt"    ) ) d= d > d2 ? 0.0 : 1.0;
145
120
    else if( strmatch(next, "lte"    ) ) d= d >= d2 ? 0.0 : 1.0;
146
121
    else if( strmatch(next, "eq"    ) ) d= d == d2 ? 1.0 : 0.0;
 
122
    else if( strmatch(next, "("     ) ) d= d;
147
123
//    else if( strmatch(next, "l1"    ) ) d= 1 + d2*(d - 1);
148
124
//    else if( strmatch(next, "sq01"  ) ) d= (d >= 0.0 && d <=1.0) ? 1.0 : 0.0;
149
125
    else{
150
 
        int error=1;
151
126
        for(i=0; p->func1_name && p->func1_name[i]; i++){
152
127
            if(strmatch(next, p->func1_name[i])){
153
 
                d= p->func1[i](p->opaque, d);
154
 
                error=0;
155
 
                break;
 
128
                return p->func1[i](p->opaque, d);
156
129
            }
157
130
        }
158
131
 
159
132
        for(i=0; p->func2_name && p->func2_name[i]; i++){
160
133
            if(strmatch(next, p->func2_name[i])){
161
 
                d= p->func2[i](p->opaque, d, d2);
162
 
                error=0;
163
 
                break;
 
134
                return p->func2[i](p->opaque, d, d2);
164
135
            }
165
136
        }
166
137
 
167
 
        if(error){
168
 
            av_log(NULL, AV_LOG_ERROR, "Parser: unknown function in \"%s\"\n", next);
169
 
            return;
170
 
        }
 
138
        av_log(NULL, AV_LOG_ERROR, "Parser: unknown function in \"%s\"\n", next);
 
139
        return NAN;
171
140
    }
172
 
    
173
 
    push(p, d);
 
141
 
 
142
    return d;
174
143
}      
175
 
       
176
 
static void evalPow(Parser *p){
177
 
    int neg= 0;
178
 
    if(p->s[0]=='+') p->s++;
179
 
       
180
 
    if(p->s[0]=='-'){ 
181
 
        neg= 1;
182
 
        p->s++;
183
 
    }
184
 
    
185
 
    if(p->s[0]=='('){
186
 
        p->s++;;
187
 
        evalExpression(p);
188
144
 
189
 
        if(p->s[0]!=')')
190
 
            av_log(NULL, AV_LOG_ERROR, "Parser: missing )\n");
191
 
        p->s++;
192
 
    }else{
193
 
        evalPrimary(p);
194
 
    }
195
 
    
196
 
    if(neg) push(p, -pop(p));
 
145
static double evalPow(Parser *p){
 
146
    int sign= (*p->s == '+') - (*p->s == '-');
 
147
    p->s += sign&1;
 
148
    return (sign|1) * evalPrimary(p);
197
149
}
198
150
 
199
 
static void evalFactor(Parser *p){
200
 
    evalPow(p);
 
151
static double evalFactor(Parser *p){
 
152
    double ret= evalPow(p);
201
153
    while(p->s[0]=='^'){
202
 
        double d;
203
 
 
204
154
        p->s++;
205
 
        evalPow(p);
206
 
        d= pop(p);
207
 
        push(p, pow(pop(p), d));
 
155
        ret= pow(ret, evalPow(p));
208
156
    }
 
157
    return ret;
209
158
}
210
159
 
211
 
static void evalTerm(Parser *p){
212
 
    evalFactor(p);
 
160
static double evalTerm(Parser *p){
 
161
    double ret= evalFactor(p);
213
162
    while(p->s[0]=='*' || p->s[0]=='/'){
214
 
        int inv= p->s[0]=='/';
215
 
        double d;
216
 
 
217
 
        p->s++;
218
 
        evalFactor(p);
219
 
        d= pop(p);
220
 
        if(inv) d= 1.0/d;
221
 
        push(p, d * pop(p));
 
163
        if(*p->s++ == '*') ret*= evalFactor(p);
 
164
        else               ret/= evalFactor(p);
222
165
    }
 
166
    return ret;
223
167
}
224
168
 
225
 
static void evalExpression(Parser *p){
226
 
    evalTerm(p);
227
 
    while(p->s[0]=='+' || p->s[0]=='-'){
228
 
        int sign= p->s[0]=='-';
229
 
        double d;
230
 
 
231
 
        p->s++;
232
 
        evalTerm(p);
233
 
        d= pop(p);
234
 
        if(sign) d= -d;
235
 
        push(p, d + pop(p));
236
 
    }
 
169
static double evalExpression(Parser *p){
 
170
    double ret= 0;
 
171
 
 
172
    if(p->stack_index <= 0) //protect against stack overflows
 
173
        return NAN;
 
174
    p->stack_index--;
 
175
 
 
176
    do{
 
177
        ret += evalTerm(p);
 
178
    }while(*p->s == '+' || *p->s == '-');
 
179
 
 
180
    p->stack_index++;
 
181
 
 
182
    return ret;
237
183
}
238
184
 
239
185
double ff_eval(char *s, double *const_value, const char **const_name,
242
188
               void *opaque){
243
189
    Parser p;
244
190
    
245
 
    p.stack_index=0;
 
191
    p.stack_index=100;
246
192
    p.s= s;
247
193
    p.const_value= const_value;
248
194
    p.const_name = const_name;
252
198
    p.func2_name = func2_name;
253
199
    p.opaque     = opaque;
254
200
    
255
 
    evalExpression(&p);
256
 
    return pop(&p);
257
 
}
 
201
    return evalExpression(&p);
 
202
}
 
203
 
 
204
#ifdef TEST
 
205
#undef printf 
 
206
static double const_values[]={
 
207
    M_PI,
 
208
    M_E,
 
209
    0
 
210
};
 
211
static const char *const_names[]={
 
212
    "PI",
 
213
    "E",
 
214
    0
 
215
};
 
216
main(){
 
217
    int i;
 
218
    printf("%f == 12.7\n", ff_eval("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL));
 
219
    
 
220
    for(i=0; i<1050; i++){
 
221
        START_TIMER
 
222
            ff_eval("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL);
 
223
        STOP_TIMER("ff_eval")
 
224
    }
 
225
}
 
226
#endif