Commit 400246dc authored by Bernhard Link's avatar Bernhard Link

fix bad character checking, check conf/distribution for sane Codename,...

fix bad character checking, check conf/distribution for sane Codename, Component and Architecture values
parent 69235292
......@@ -2,6 +2,10 @@
* Add --onlyacceptsigned to make include and includedsc only
accept signed files.
* Check Codename, Components and Architectures fields
of conf/distributions for sane values
* fix checks for strange characters
2005-02-03 Bernhard R. Link <brlink@debian.org>
* When updating delete files lists/<codename>_ for
all updated distributions, which will not be needed any more.
......
TODO:
check values from conf/distributions for sane values
write more automated test-cases
goals unlikely before the first release:
......
......@@ -132,9 +132,26 @@ static retvalue createtargets(struct distribution *distribution) {
return RET_OK;
}
static retvalue distribution_parse(struct distribution **distribution,const char *chunk) {
struct distribution_filter {int count; const char **dists; };
static inline bool_t isinfilter(const char *codename, const struct distribution_filter filter){
int i;
/* nothing given means all */
if( filter.count <= 0 )
return TRUE;
for( i = 0 ; i < filter.count ; i++ ) {
if( strcmp((filter.dists)[i],codename) == 0 )
return TRUE;
}
return FALSE;
}
static retvalue distribution_parse_and_filter(struct distribution **distribution,const char *chunk,struct distribution_filter filter) {
struct distribution *r;
retvalue ret;
const char *missing;
static const char * const allowedfields[] = {
"Codename", "Suite", "Version", "Origin", "Label", "Description",
"Architectures", "Components", "Update", "SignWith", "Override",
......@@ -156,15 +173,18 @@ static const char * const allowedfields[] = {
ret = chunk_getvalue(chunk,"Codename",&r->codename);
fieldrequired("Codename");
if( RET_IS_OK(ret) )
ret = propercodename(r->codename);
if( RET_WAS_ERROR(ret) ) {
(void)distribution_free(r);
return ret;
}
#define nullifnone(a) if(RET_WAS_ERROR(ret)) { \
(void)distribution_free(r); \
return ret; \
} else r->a = NULL;
if( !isinfilter(r->codename,filter) ) {
(void)distribution_free(r);
return RET_NOTHING;
}
#define getpossibleemptyfield(key,fieldname) \
ret = chunk_getvalue(chunk,key,&r->fieldname); \
if(RET_WAS_ERROR(ret)) { \
......@@ -172,6 +192,15 @@ static const char * const allowedfields[] = {
return ret; \
} else if( ret == RET_NOTHING) \
r->fieldname = NULL;
#define getpossibleemptywordlist(key,fieldname) \
ret = chunk_getwordlist(chunk,key,&r->fieldname); \
if(RET_WAS_ERROR(ret)) { \
(void)distribution_free(r); \
return ret; \
} else if( ret == RET_NOTHING) { \
r->fieldname.count = 0; \
r->fieldname.values = NULL; \
}
getpossibleemptyfield("Suite",suite);
getpossibleemptyfield("Version",version);
......@@ -180,12 +209,16 @@ static const char * const allowedfields[] = {
getpossibleemptyfield("Description",description);
ret = chunk_getwordlist(chunk,"Architectures",&r->architectures);
fieldrequired("Architectures");
if( RET_IS_OK(ret) )
ret = properarchitectures(&r->architectures);
if( RET_WAS_ERROR(ret) ) {
(void)distribution_free(r);
return ret;
}
ret = chunk_getwordlist(chunk,"Components",&r->components);
fieldrequired("Components");
if( RET_IS_OK(ret) )
ret = propercomponents(&r->components);
if( RET_WAS_ERROR(ret) ) {
(void)distribution_free(r);
return ret;
......@@ -198,8 +231,15 @@ static const char * const allowedfields[] = {
getpossibleemptyfield("SignWith",signwith);
getpossibleemptyfield("Override",override);
getpossibleemptyfield("SourceOverride",srcoverride);
ret = chunk_getwordlist(chunk,"UDebComponents",&r->udebcomponents);
if( RET_WAS_ERROR(ret) ) {
getpossibleemptywordlist("UDebComponents",udebcomponents);
// TODO: instead of checking here make sure it can have more
// in the rest of the code...
if( !strlist_subset(&r->components,&r->udebcomponents,&missing) ) {
fprintf(stderr,"In distribution description of '%s':\n"
"UDebComponent contains '%s' not found in Components!\n",
r->codename,missing);
(void)distribution_free(r);
return ret;
}
......@@ -215,31 +255,7 @@ static const char * const allowedfields[] = {
#undef fieldrequired
#undef getpossibleemptyfield
}
struct distribution_filter {int count; const char **dists; };
static retvalue distribution_parse_and_filter(struct distribution **distribution,const char *chunk,struct distribution_filter filter) {
retvalue result;
int i;
// TODO: combine this with distribution_parse, so that
// there is no need to read anything in even when it
// is not the correct one...
result = distribution_parse(distribution,chunk);
if( RET_IS_OK(result) ) {
if( filter.count > 0 ) {
i = filter.count;
while( i-- > 0 && strcmp((filter.dists)[i],(*distribution)->codename) != 0 ) {
}
if( i < 0 ) {
(void)distribution_free(*distribution);
*distribution = NULL;
return RET_NOTHING;
}
}
}
return result;
#undef getpossibleemptywordlist
}
/* call <action> for each part of <distribution>. */
......
......@@ -62,6 +62,23 @@ static inline bool_t overlongUTF8(const char *character) {
return FALSE;
}
#define REJECTLOWCHARS(s,str,descr) \
if( (unsigned char)*s < ' ' ) { \
fprintf(stderr, \
"Character 0x%02hhx not allowed within %s '%s'!\n", \
*s,descr,str); \
return RET_ERROR; \
}
#define REJECTCHARIF(c,s,str,descr) \
if( c ) { \
fprintf(stderr, \
"Character '%c' not allowed within %s '%s'!\n", \
*s,descr,string); \
return RET_ERROR; \
}
/* check if this is something that can be used as directory safely */
retvalue propersourcename(const char *string) {
const char *s;
......@@ -85,16 +102,14 @@ retvalue propersourcename(const char *string) {
(*s > '9' || *s < '0' ) &&
(firstcharacter ||
( *s != '+' && *s != '-' && *s != '.'))) {
if( *s < ' ' || *s == '/' ) {
fprintf(stderr,"Character 0x%2x not allowed within sourcename '%s'!\n",(unsigned int)*s,string);
return RET_ERROR;
}
REJECTLOWCHARS(s,string,"sourcename");
REJECTCHARIF( *s == '/', s,string, "sourcename");
if( overlongUTF8(s) ) {
fprintf(stderr,"This could contain an overlong UTF8-sequence, rejecting sourcename '%s'!\n",string);
return RET_ERROR;
}
if( !IGNORING(
"Not rejecting","To ignore this",forbiddenchar,"Character 0x%2x not allowed in sourcename: '%s'!\n",(unsigned int)*s,string) ) {
"Not rejecting","To ignore this",forbiddenchar,"Character 0x%02hhx not allowed in sourcename: '%s'!\n",*s,string) ) {
return RET_ERROR;
}
if( *s & 0x80 ) {
......@@ -123,12 +138,9 @@ retvalue properfilename(const char *string) {
fprintf(stderr,"Filename not allowed: '%s'!\n",string);
return RET_ERROR;
}
s = string;
while( *s ) {
if( *s < ' ' || *s == '/' ) {
fprintf(stderr,"Character 0x%2x not allowed within filename '%s'!\n",(unsigned int)*s,string);
return RET_ERROR;
}
for( s = string ; *s ; s++ ) {
REJECTLOWCHARS(s,string,"filename");
REJECTCHARIF( *s == '/' ,s,string,"filename");
if( *s & 0x80 ) {
if( overlongUTF8(s) ) {
fprintf(stderr,"This could contain an overlong UTF8-sequence, rejecting filename '%s'!\n",string);
......@@ -139,38 +151,102 @@ retvalue properfilename(const char *string) {
return RET_ERROR;
}
}
s++;
}
return RET_OK;
}
retvalue properidentiferpart(const char *string) {
static retvalue properidentifierpart(const char *string,const char *description) {
const char *s;
if( string[0] == '\0' && !IGNORING(
"Ignoring","To ignore this",emptyfilenamepart,"A string to be used of an filename is empty!\n") ) {
return RET_ERROR;
}
for( s = string; *s ; s++ ) {
REJECTLOWCHARS(s,string,description);
REJECTCHARIF( *s == '|' || *s == '/' ,s,string,description);
}
return RET_OK;
}
retvalue properarchitectures(const struct strlist *architectures) {
int i;
retvalue r;
for( i = 0 ; i < architectures->count ; i++ ) {
r = properidentifierpart(architectures->values[i],"architecture");
if( RET_WAS_ERROR(r) )
return r;
}
return RET_OK;
}
/* check if this is something that can be used as directory *and* identifer safely */
static retvalue properdirectoryandidentifier(const char *string, const char *description) {
const char *s;
if( string[0] == '\0' ) {
fprintf(stderr,"Error: empty %s!\n",description);
return RET_ERROR;
}
if( (string[0] == '.' && (string[1] == '\0'||string[1]=='/')) ||
(string[0] == '.' && string[1] == '.' &&
(string[2] == '\0'||string[2] =='/')) ) {
fprintf(stderr,"%s cannot be '%s', as it is used as directory!\n",description,string);
return RET_ERROR;
}
s = string;
while( *s ) {
if( *s < ' ' || *s == '|' ) {
fprintf(stderr,"Character 0x%2x not allowed within identifier '%s'!\n",(unsigned int)*s,string);
REJECTLOWCHARS(s,string,description);
REJECTCHARIF( *s == '|' ,s,string,description);
if( *s == '/' &&
((s[1] == '.' && (s[2] == '\0' || s[2] == '/' ) ) ||
(s[1] == '.' && s[2] == '.' &&
(s[3] == '\0' || s[3] =='/')))) {
fprintf(stderr,"%s cannot be '%s': directory parts . or .. in it!\n",description,string);
return RET_ERROR;
}
if( *s == '/' && s[1] == '/' ) {
fprintf(stderr,"%s '%s' should have only single '/'!\n",description,string);
return RET_ERROR;
}
if( *s & 0x80 ) {
if( overlongUTF8(s) ) {
fprintf(stderr,"This could contain an overlong UTF8-sequence, rejecting %s '%s'!\n",description,string);
return RET_ERROR;
}
if( !IGNORING(
"Not rejecting","To ignore this",8bit,"8bit character in %s: '%s'!\n",description,string)) {
return RET_ERROR;
}
}
s++;
}
return RET_OK;
}
retvalue propercomponents(const struct strlist *components) {
int i;
retvalue r;
for( i = 0 ; i < components->count ; i++ ) {
r = properdirectoryandidentifier(components->values[i],"Component");
if( RET_WAS_ERROR(r) )
return r;
}
return RET_OK;
}
retvalue propercodename(const char *codename) {
return properdirectoryandidentifier(codename,"Codename");
}
retvalue properfilenamepart(const char *string) {
const char *s;
s = string;
while( *s ) {
if( *s < ' ' || *s == '/' ) {
fprintf(stderr,"Character 0x%2x not allowed within filenamepart '%s'!\n",(unsigned int)*s,string);
return RET_ERROR;
}
for( s = string ; *s ; s++ ) {
REJECTLOWCHARS(s,string,"filenamepart");
REJECTCHARIF( *s == '/' ,s,string,"filenamepart");
if( *s & 0x80 ) {
if( overlongUTF8(s) ) {
fprintf(stderr,"This could contain an overlong UTF8-sequence, rejecting filenamepart '%s'!\n",string);
......@@ -181,7 +257,6 @@ retvalue properfilenamepart(const char *string) {
return RET_ERROR;
}
}
s++;
}
return RET_OK;
}
......@@ -221,10 +296,8 @@ retvalue properversion(const char *string) {
if( first || (*s != '+' && *s != '-' &&
*s != '.' && *s != '~' &&
(!hadepoch || *s != ':' ))) {
if( *s < ' ' || *s == '/' ) {
fprintf(stderr,"Character 0x%2x not allowed within sourcename '%s'!\n",(unsigned int)*s,string);
return RET_ERROR;
}
REJECTLOWCHARS(s,string,"version");
REJECTCHARIF( *s == '/' ,s,string,"version");
if( overlongUTF8(s) ) {
fprintf(stderr,"This could contain an overlong UTF8-sequence, rejecting version '%s'!\n",string);
return RET_ERROR;
......@@ -278,16 +351,14 @@ retvalue properpackagename(const char *string) {
(*s > '9' || *s < '0' ) &&
( firstcharacter ||
(*s != '+' && *s != '-' && *s != '.'))) {
if( *s < ' ' || *s == '/' ) {
fprintf(stderr,"Character 0x%2x not allowed within package name '%s'!\n",(unsigned int)*s,string);
return RET_ERROR;
}
REJECTLOWCHARS(s,string,"package name");
REJECTCHARIF( *s == '/' ,s,string,"package name");
if( overlongUTF8(s) ) {
fprintf(stderr,"This could contain an overlong UTF8-sequence, rejecting package name '%s'!\n",string);
return RET_ERROR;
}
if( !IGNORING(
"Not rejecting","To ignore this",forbiddenchar,"Character 0x%2x not allowed in package name: '%s'!\n",(unsigned int)*s,string) ) {
"Not rejecting","To ignore this",forbiddenchar,"Character 0x%02hhx not allowed in package name: '%s'!\n",*s,string) ) {
return RET_ERROR;
}
if( *s & 0x80 ) {
......
......@@ -40,6 +40,8 @@ retvalue properfilename(const char *string);
retvalue properfilenames(const struct strlist *names);
retvalue properpackagename(const char *string);
retvalue properversion(const char *string);
retvalue properidentifierpart(const char *string);
retvalue propercodename(const char *codename);
retvalue properarchitectures(const struct strlist *architectures);
retvalue propercomponents(const struct strlist *components);
#endif
/* This file is part of "reprepro"
* Copyright (C) 2003 Bernhard R. Link
* Copyright (C) 2003,2005 Bernhard R. Link
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
......@@ -39,7 +39,7 @@ bool_t strlist_in(const struct strlist *strlist,const char *element) {
return FALSE;
}
bool_t strlist_subset(const struct strlist *strlist,const struct strlist *subset) {
bool_t strlist_subset(const struct strlist *strlist,const struct strlist *subset,const char **missing) {
int c;
char **t;
......@@ -48,8 +48,11 @@ bool_t strlist_subset(const struct strlist *strlist,const struct strlist *subset
c = subset->count;
t = subset->values;
while( c-- != 0 ) {
if( !strlist_in(strlist,*(t++)) )
if( !strlist_in(strlist,*(t++)) ) {
if( missing )
*missing = *(t-1);
return FALSE;
}
}
return TRUE;
......
......@@ -34,6 +34,8 @@ void strlist_move(struct strlist *dest,struct strlist *orig);
retvalue strlist_mvadd(struct strlist *dest,struct strlist *orig);
bool_t strlist_in(const struct strlist *strlist,const char *element);
bool_t strlist_subset(const struct strlist *strlist,const struct strlist *subset);
/* if missing != NULL And subset no subset of strlist, set *missing to the first missing one */
bool_t strlist_subset(const struct strlist *strlist,const struct strlist *subset,const char **missing);
#endif
......@@ -325,8 +325,8 @@ static retvalue checkpkg(void *data,const char *package,const char *chunk) {
if( RET_IS_OK(r) ) {
free(version);
free(dummy);
if( !strlist_subset(&expectedfilekeys,&actualfilekeys) ||
!strlist_subset(&expectedfilekeys,&actualfilekeys) ) {
if( !strlist_subset(&expectedfilekeys,&actualfilekeys,NULL) ||
!strlist_subset(&expectedfilekeys,&actualfilekeys,NULL) ) {
fprintf(stderr,"Reparsing the package information of '%s' yields to the expectation to find:\n",package);
strlist_fprint(stderr,&expectedfilekeys);
fputs("but found:\n",stderr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment