@@ -310,6 +310,12 @@ typedef enum {
310310 to be returned in r->status */
311311} rule_return_type ;
312312
313+ typedef enum {
314+ COND_RC_NOMATCH = 0 , /* the cond didn't match */
315+ COND_RC_MATCH = 1 , /* the cond matched */
316+ COND_RC_STATUS_SET = 3 /* The condition eval set a final r->status */
317+ } cond_return_type ;
318+
313319typedef struct {
314320 char * input ; /* Input string of RewriteCond */
315321 char * pattern ; /* the RegExp pattern string */
@@ -4111,62 +4117,87 @@ static APR_INLINE int compare_lexicography(char *a, char *b)
41114117/*
41124118 * Apply a single rewriteCond
41134119 */
4114- static int apply_rewrite_cond (rewritecond_entry * p , rewrite_ctx * ctx , apr_pool_t * pool )
4120+ static cond_return_type apply_rewrite_cond (rewritecond_entry * p , rewrite_ctx * ctx , apr_pool_t * pool )
41154121{
41164122 char * input = NULL ;
41174123 apr_finfo_t sb ;
41184124 request_rec * rsub , * r = ctx -> r ;
41194125 ap_regmatch_t regmatch [AP_MAX_REG_MATCH ];
4120- int rc = 0 ;
4126+ int rc = COND_RC_NOMATCH ;
41214127 int basis ;
41224128
41234129 if (p -> ptype != CONDPAT_AP_EXPR )
41244130 input = do_expand (p -> input , ctx , NULL , NULL , pool );
41254131
41264132 switch (p -> ptype ) {
41274133 case CONDPAT_FILE_EXISTS :
4134+ if (APR_SUCCESS != ap_stat_check (input , r -> pool )) {
4135+ r -> status = HTTP_FORBIDDEN ;
4136+ rewritelog (r , 4 , ctx -> perdir , "RewriteCond: refusing to stat input='%s'" , input );
4137+ return COND_RC_STATUS_SET ;
4138+ }
41284139 if ( apr_stat (& sb , input , APR_FINFO_MIN , r -> pool ) == APR_SUCCESS
41294140 && sb .filetype == APR_REG ) {
4130- rc = 1 ;
4141+ rc = COND_RC_MATCH ;
41314142 }
41324143 break ;
41334144
41344145 case CONDPAT_FILE_SIZE :
4146+ if (APR_SUCCESS != ap_stat_check (input , r -> pool )) {
4147+ r -> status = HTTP_FORBIDDEN ;
4148+ rewritelog (r , 4 , ctx -> perdir , "RewriteCond: refusing to stat input='%s'" , input );
4149+ return COND_RC_STATUS_SET ;
4150+ }
41354151 if ( apr_stat (& sb , input , APR_FINFO_MIN , r -> pool ) == APR_SUCCESS
41364152 && sb .filetype == APR_REG && sb .size > 0 ) {
4137- rc = 1 ;
4153+ rc = COND_RC_MATCH ;
41384154 }
41394155 break ;
41404156
41414157 case CONDPAT_FILE_LINK :
4158+ if (APR_SUCCESS != ap_stat_check (input , r -> pool )) {
4159+ r -> status = HTTP_FORBIDDEN ;
4160+ rewritelog (r , 4 , ctx -> perdir , "RewriteCond: refusing to stat input='%s'" , input );
4161+ return COND_RC_STATUS_SET ;
4162+ }
41424163#if !defined(OS2 )
41434164 if ( apr_stat (& sb , input , APR_FINFO_MIN | APR_FINFO_LINK ,
41444165 r -> pool ) == APR_SUCCESS
41454166 && sb .filetype == APR_LNK ) {
4146- rc = 1 ;
4167+ rc = COND_RC_MATCH ;
41474168 }
41484169#endif
41494170 break ;
41504171
41514172 case CONDPAT_FILE_DIR :
4173+ if (APR_SUCCESS != ap_stat_check (input , r -> pool )) {
4174+ r -> status = HTTP_FORBIDDEN ;
4175+ rewritelog (r , 4 , ctx -> perdir , "RewriteCond: refusing to stat input='%s'" , input );
4176+ return COND_RC_STATUS_SET ;
4177+ }
41524178 if ( apr_stat (& sb , input , APR_FINFO_MIN , r -> pool ) == APR_SUCCESS
41534179 && sb .filetype == APR_DIR ) {
4154- rc = 1 ;
4180+ rc = COND_RC_MATCH ;
41554181 }
41564182 break ;
41574183
41584184 case CONDPAT_FILE_XBIT :
4185+ if (APR_SUCCESS != ap_stat_check (input , r -> pool )) {
4186+ r -> status = HTTP_FORBIDDEN ;
4187+ rewritelog (r , 4 , ctx -> perdir , "RewriteCond: refusing to stat input='%s'" , input );
4188+ return COND_RC_STATUS_SET ;
4189+ }
41594190 if ( apr_stat (& sb , input , APR_FINFO_PROT , r -> pool ) == APR_SUCCESS
41604191 && (sb .protection & (APR_UEXECUTE | APR_GEXECUTE | APR_WEXECUTE ))) {
4161- rc = 1 ;
4192+ rc = COND_RC_MATCH ;
41624193 }
41634194 break ;
41644195
41654196 case CONDPAT_LU_URL :
41664197 if (* input && subreq_ok (r )) {
41674198 rsub = ap_sub_req_lookup_uri (input , r , NULL );
41684199 if (rsub -> status < 400 ) {
4169- rc = 1 ;
4200+ rc = COND_RC_MATCH ;
41704201 }
41714202 rewritelog (r , 5 , NULL , "RewriteCond URI (-U check: "
41724203 "path=%s -> status=%d" , input , rsub -> status );
@@ -4176,12 +4207,17 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx, apr_pool_t
41764207
41774208 case CONDPAT_LU_FILE :
41784209 if (* input && subreq_ok (r )) {
4210+ if (APR_SUCCESS != ap_stat_check (input , r -> pool )) {
4211+ r -> status = HTTP_FORBIDDEN ;
4212+ rewritelog (r , 4 , ctx -> perdir , "RewriteCond: refusing to stat input='%s'" , input );
4213+ return COND_RC_STATUS_SET ;
4214+ }
41794215 rsub = ap_sub_req_lookup_file (input , r , NULL );
41804216 if (rsub -> status < 300 &&
41814217 /* double-check that file exists since default result is 200 */
41824218 apr_stat (& sb , rsub -> filename , APR_FINFO_MIN ,
41834219 r -> pool ) == APR_SUCCESS ) {
4184- rc = 1 ;
4220+ rc = COND_RC_MATCH ;
41854221 }
41864222 rewritelog (r , 5 , NULL , "RewriteCond file (-F check: path=%s "
41874223 "-> file=%s status=%d" , input , rsub -> filename ,
@@ -4197,10 +4233,10 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx, apr_pool_t
41974233 basis = 1 ;
41984234test_str_g :
41994235 if (p -> flags & CONDFLAG_NOCASE ) {
4200- rc = (strcasecmp (input , p -> pattern ) >= basis ) ? 1 : 0 ;
4236+ rc = (strcasecmp (input , p -> pattern ) >= basis ) ? COND_RC_MATCH : COND_RC_NOMATCH ;
42014237 }
42024238 else {
4203- rc = (compare_lexicography (input , p -> pattern ) >= basis ) ? 1 : 0 ;
4239+ rc = (compare_lexicography (input , p -> pattern ) >= basis ) ? COND_RC_MATCH : COND_RC_NOMATCH ;
42044240 }
42054241 break ;
42064242
@@ -4211,10 +4247,10 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx, apr_pool_t
42114247 basis = -1 ;
42124248test_str_l :
42134249 if (p -> flags & CONDFLAG_NOCASE ) {
4214- rc = (strcasecmp (input , p -> pattern ) <= basis ) ? 1 : 0 ;
4250+ rc = (strcasecmp (input , p -> pattern ) <= basis ) ? COND_RC_MATCH : COND_RC_NOMATCH ;
42154251 }
42164252 else {
4217- rc = (compare_lexicography (input , p -> pattern ) <= basis ) ? 1 : 0 ;
4253+ rc = (compare_lexicography (input , p -> pattern ) <= basis ) ? COND_RC_MATCH : COND_RC_NOMATCH ;
42184254 }
42194255 break ;
42204256
@@ -4245,7 +4281,10 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx, apr_pool_t
42454281 rewritelog (r , 1 , ctx -> perdir ,
42464282 "RewriteCond: expr='%s' evaluation failed: %s" ,
42474283 p -> pattern - p -> pskip , err );
4248- rc = 0 ;
4284+ rc = COND_RC_NOMATCH ;
4285+ }
4286+ else {
4287+ rc = COND_RC_MATCH ;
42494288 }
42504289 /* update briRC backref info */
42514290 if (rc && !(p -> flags & CONDFLAG_NOTMATCH )) {
@@ -4266,7 +4305,7 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx, apr_pool_t
42664305 break ;
42674306 }
42684307
4269- if (p -> flags & CONDFLAG_NOTMATCH ) {
4308+ if (p -> flags & CONDFLAG_NOTMATCH && rc <= COND_RC_MATCH ) {
42704309 rc = !rc ;
42714310 }
42724311
@@ -4399,6 +4438,12 @@ static rule_return_type apply_rewrite_rule(rewriterule_entry *p,
43994438 rewritecond_entry * c = & conds [i ];
44004439
44014440 rc = apply_rewrite_cond (c , ctx , ctx -> temp_pool ? ctx -> temp_pool : r -> pool );
4441+
4442+ /* Error while evaluating cond, r->status set */
4443+ if (COND_RC_STATUS_SET == rc ) {
4444+ return RULE_RC_STATUS_SET ;
4445+ }
4446+
44024447 /*
44034448 * Reset vary_this if the novary flag is set for this condition.
44044449 */
0 commit comments