@@ -319,6 +319,12 @@ typedef enum {
319319 to be returned in r->status */
320320} rule_return_type ;
321321
322+ typedef enum {
323+ COND_RC_NOMATCH = 0 , /* the cond didn't match */
324+ COND_RC_MATCH = 1 , /* the cond matched */
325+ COND_RC_STATUS_SET = 3 /* The condition eval set a final r->status */
326+ } cond_return_type ;
327+
322328typedef struct {
323329 char * input ; /* Input string of RewriteCond */
324330 char * pattern ; /* the RegExp pattern string */
@@ -4103,62 +4109,87 @@ static APR_INLINE int compare_lexicography(char *a, char *b)
41034109/*
41044110 * Apply a single rewriteCond
41054111 */
4106- static int apply_rewrite_cond (rewritecond_entry * p , rewrite_ctx * ctx )
4112+ static cond_return_type apply_rewrite_cond (rewritecond_entry * p , rewrite_ctx * ctx )
41074113{
41084114 char * input = NULL ;
41094115 apr_finfo_t sb ;
41104116 request_rec * rsub , * r = ctx -> r ;
41114117 ap_regmatch_t regmatch [AP_MAX_REG_MATCH ];
4112- int rc = 0 ;
4118+ int rc = COND_RC_NOMATCH ;
41134119 int basis ;
41144120
41154121 if (p -> ptype != CONDPAT_AP_EXPR )
41164122 input = do_expand (p -> input , ctx , NULL , NULL );
41174123
41184124 switch (p -> ptype ) {
41194125 case CONDPAT_FILE_EXISTS :
4126+ if (APR_SUCCESS != ap_stat_check (input , r -> pool )) {
4127+ r -> status = HTTP_FORBIDDEN ;
4128+ rewritelog (r , 4 , ctx -> perdir , "RewriteCond: refusing to stat input='%s'" , input );
4129+ return COND_RC_STATUS_SET ;
4130+ }
41204131 if ( apr_stat (& sb , input , APR_FINFO_MIN , r -> pool ) == APR_SUCCESS
41214132 && sb .filetype == APR_REG ) {
4122- rc = 1 ;
4133+ rc = COND_RC_MATCH ;
41234134 }
41244135 break ;
41254136
41264137 case CONDPAT_FILE_SIZE :
4138+ if (APR_SUCCESS != ap_stat_check (input , r -> pool )) {
4139+ r -> status = HTTP_FORBIDDEN ;
4140+ rewritelog (r , 4 , ctx -> perdir , "RewriteCond: refusing to stat input='%s'" , input );
4141+ return COND_RC_STATUS_SET ;
4142+ }
41274143 if ( apr_stat (& sb , input , APR_FINFO_MIN , r -> pool ) == APR_SUCCESS
41284144 && sb .filetype == APR_REG && sb .size > 0 ) {
4129- rc = 1 ;
4145+ rc = COND_RC_MATCH ;
41304146 }
41314147 break ;
41324148
41334149 case CONDPAT_FILE_LINK :
4150+ if (APR_SUCCESS != ap_stat_check (input , r -> pool )) {
4151+ r -> status = HTTP_FORBIDDEN ;
4152+ rewritelog (r , 4 , ctx -> perdir , "RewriteCond: refusing to stat input='%s'" , input );
4153+ return COND_RC_STATUS_SET ;
4154+ }
41344155#if !defined(OS2 )
41354156 if ( apr_stat (& sb , input , APR_FINFO_MIN | APR_FINFO_LINK ,
41364157 r -> pool ) == APR_SUCCESS
41374158 && sb .filetype == APR_LNK ) {
4138- rc = 1 ;
4159+ rc = COND_RC_MATCH ;
41394160 }
41404161#endif
41414162 break ;
41424163
41434164 case CONDPAT_FILE_DIR :
4165+ if (APR_SUCCESS != ap_stat_check (input , r -> pool )) {
4166+ r -> status = HTTP_FORBIDDEN ;
4167+ rewritelog (r , 4 , ctx -> perdir , "RewriteCond: refusing to stat input='%s'" , input );
4168+ return COND_RC_STATUS_SET ;
4169+ }
41444170 if ( apr_stat (& sb , input , APR_FINFO_MIN , r -> pool ) == APR_SUCCESS
41454171 && sb .filetype == APR_DIR ) {
4146- rc = 1 ;
4172+ rc = COND_RC_MATCH ;
41474173 }
41484174 break ;
41494175
41504176 case CONDPAT_FILE_XBIT :
4177+ if (APR_SUCCESS != ap_stat_check (input , r -> pool )) {
4178+ r -> status = HTTP_FORBIDDEN ;
4179+ rewritelog (r , 4 , ctx -> perdir , "RewriteCond: refusing to stat input='%s'" , input );
4180+ return COND_RC_STATUS_SET ;
4181+ }
41514182 if ( apr_stat (& sb , input , APR_FINFO_PROT , r -> pool ) == APR_SUCCESS
41524183 && (sb .protection & (APR_UEXECUTE | APR_GEXECUTE | APR_WEXECUTE ))) {
4153- rc = 1 ;
4184+ rc = COND_RC_MATCH ;
41544185 }
41554186 break ;
41564187
41574188 case CONDPAT_LU_URL :
41584189 if (* input && subreq_ok (r )) {
41594190 rsub = ap_sub_req_lookup_uri (input , r , NULL );
41604191 if (rsub -> status < 400 ) {
4161- rc = 1 ;
4192+ rc = COND_RC_MATCH ;
41624193 }
41634194 rewritelog (r , 5 , NULL , "RewriteCond URI (-U check: "
41644195 "path=%s -> status=%d" , input , rsub -> status );
@@ -4168,12 +4199,17 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx)
41684199
41694200 case CONDPAT_LU_FILE :
41704201 if (* input && subreq_ok (r )) {
4202+ if (APR_SUCCESS != ap_stat_check (input , r -> pool )) {
4203+ r -> status = HTTP_FORBIDDEN ;
4204+ rewritelog (r , 4 , ctx -> perdir , "RewriteCond: refusing to stat input='%s'" , input );
4205+ return COND_RC_STATUS_SET ;
4206+ }
41714207 rsub = ap_sub_req_lookup_file (input , r , NULL );
41724208 if (rsub -> status < 300 &&
41734209 /* double-check that file exists since default result is 200 */
41744210 apr_stat (& sb , rsub -> filename , APR_FINFO_MIN ,
41754211 r -> pool ) == APR_SUCCESS ) {
4176- rc = 1 ;
4212+ rc = COND_RC_MATCH ;
41774213 }
41784214 rewritelog (r , 5 , NULL , "RewriteCond file (-F check: path=%s "
41794215 "-> file=%s status=%d" , input , rsub -> filename ,
@@ -4189,10 +4225,10 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx)
41894225 basis = 1 ;
41904226test_str_g :
41914227 if (p -> flags & CONDFLAG_NOCASE ) {
4192- rc = (strcasecmp (input , p -> pattern ) >= basis ) ? 1 : 0 ;
4228+ rc = (strcasecmp (input , p -> pattern ) >= basis ) ? COND_RC_MATCH : COND_RC_NOMATCH ;
41934229 }
41944230 else {
4195- rc = (compare_lexicography (input , p -> pattern ) >= basis ) ? 1 : 0 ;
4231+ rc = (compare_lexicography (input , p -> pattern ) >= basis ) ? COND_RC_MATCH : COND_RC_NOMATCH ;
41964232 }
41974233 break ;
41984234
@@ -4203,10 +4239,10 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx)
42034239 basis = -1 ;
42044240test_str_l :
42054241 if (p -> flags & CONDFLAG_NOCASE ) {
4206- rc = (strcasecmp (input , p -> pattern ) <= basis ) ? 1 : 0 ;
4242+ rc = (strcasecmp (input , p -> pattern ) <= basis ) ? COND_RC_MATCH : COND_RC_NOMATCH ;
42074243 }
42084244 else {
4209- rc = (compare_lexicography (input , p -> pattern ) <= basis ) ? 1 : 0 ;
4245+ rc = (compare_lexicography (input , p -> pattern ) <= basis ) ? COND_RC_MATCH : COND_RC_NOMATCH ;
42104246 }
42114247 break ;
42124248
@@ -4237,7 +4273,10 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx)
42374273 rewritelog (r , 1 , ctx -> perdir ,
42384274 "RewriteCond: expr='%s' evaluation failed: %s" ,
42394275 p -> pattern - p -> pskip , err );
4240- rc = 0 ;
4276+ rc = COND_RC_NOMATCH ;
4277+ }
4278+ else {
4279+ rc = COND_RC_MATCH ;
42414280 }
42424281 /* update briRC backref info */
42434282 if (rc && !(p -> flags & CONDFLAG_NOTMATCH )) {
@@ -4258,7 +4297,7 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx)
42584297 break ;
42594298 }
42604299
4261- if (p -> flags & CONDFLAG_NOTMATCH ) {
4300+ if (p -> flags & CONDFLAG_NOTMATCH && rc <= COND_RC_MATCH ) {
42624301 rc = !rc ;
42634302 }
42644303
@@ -4391,6 +4430,12 @@ static rule_return_type apply_rewrite_rule(rewriterule_entry *p,
43914430 rewritecond_entry * c = & conds [i ];
43924431
43934432 rc = apply_rewrite_cond (c , ctx );
4433+
4434+ /* Error while evaluating cond, r->status set */
4435+ if (COND_RC_STATUS_SET == rc ) {
4436+ return RULE_RC_STATUS_SET ;
4437+ }
4438+
43944439 /*
43954440 * Reset vary_this if the novary flag is set for this condition.
43964441 */
0 commit comments