[med-svn] [SCM] aghermann branch, master, updated. 551e213a23b59b71cba6a9c3a282d1b60e21b854
Andrei Zavada
johnhommer at gmail.com
Sun Apr 21 23:18:00 UTC 2013
The following commit has been merged in the master branch:
commit 848a2218bd194821d479bc91cbc2b6fc0ba3111f
Author: Andrei Zavada <johnhommer at gmail.com>
Date: Mon Apr 15 10:23:50 2013 +0300
fsize checks in CEDFFile ctor
diff --git a/src/libsigfile/edf.cc b/src/libsigfile/edf.cc
index 9c98118..26d9931 100644
--- a/src/libsigfile/edf.cc
+++ b/src/libsigfile/edf.cc
@@ -118,16 +118,19 @@ CEDFFile (const char *fname_, int flags_)
{
struct stat stat0;
int stst = stat( fname_, &stat0);
- if ( stst == -1 )
- throw runtime_error ("CEDFFile::CEDFFile(): stat error");
+ if ( stst == -1 ) {
+ _status |= TStatus::sysfail;
+ throw runtime_error (explain_edf_status(_status));
+ }
_fsize = stat0.st_size;
}
- // mmap
_fd = open( fname_, O_RDWR);
if ( _fd == -1 ) {
_status |= TStatus::sysfail;
- throw runtime_error ("CEDFFile::CEDFFile(): file open error");
+ throw runtime_error (explain_edf_status(_status));
}
+
+ // mmap
_mmapping =
mmap( NULL,
_fsize,
@@ -151,69 +154,89 @@ CEDFFile (const char *fname_, int flags_)
header_length = 256 + (channels.size() * 256);
- // artifacts, per signal
- if ( flags_ & sigfile::CTypedSource::no_ancillary_files )
- return;
-
- // else read artifacts, filters and annotations from external files
- for ( auto &H : channels ) {
- ifstream thomas (make_fname_artifacts( H.label));
- if ( not thomas.good() )
- continue;
-
- while ( !thomas.eof() ) {
- size_t aa = (size_t)-1, az = (size_t)-1;
- thomas >> aa >> az;
- if ( aa == (size_t)-1 || az == (size_t)-1 )
- break;
- H.artifacts.mark_artifact( aa, az);
+ // lest we ever access past mmapped region
+ {
+ size_t total_samples_per_record = 0;
+ for ( auto& H : channels )
+ total_samples_per_record += H.samples_per_record;
+ size_t expected_fsize = header_length + sizeof(int16_t) * total_samples_per_record * n_data_records;
+ if ( _fsize < expected_fsize ) {
+ fprintf( stderr, "CEDFFile::CEDFFile(\"%s\") file size less than declared in header\n", fname_);
+ close( _fd);
+ munmap( _mmapping, _fsize);
+ _status |= file_truncated;
+ throw runtime_error (explain_edf_status(_status));
+ } else if ( _fsize > expected_fsize ) {
+ _status |= trailing_junk;
+ fprintf( stderr, "CEDFFile::CEDFFile(\"%s\") Warning: %zu bytes of trailing junk\n",
+ fname_, _fsize - expected_fsize);
}
}
- // annotations, per signal
- for ( auto &H : channels ) {
- ifstream fd (make_fname_annotations( H.label));
- if ( not fd.good() )
- continue;
- int type = -1;
- size_t aa = -1, az = -1;
- string an;
- while ( fd.good() and not fd.eof() ) {
- fd >> type >> aa >> az;
- getline( fd, an, EOA);
- if ( aa < az and az < n_data_records * H.samples_per_record
- and type < SAnnotation::TType_total and type >= 0 )
- H.annotations.emplace_back(
- aa, az,
- agh::str::trim(an),
- (SAnnotation::TType)type);
- else {
- fprintf( stderr, "Bad annotation: (%d %zu %zu %50s)\n", type, aa, az, an.c_str());
- break;
+ // ancillary files:
+ if ( flags_ & sigfile::CTypedSource::no_ancillary_files )
+ ;
+ else {
+ // 1. artifacts, per signal
+ for ( auto &H : channels ) {
+ ifstream thomas (make_fname_artifacts( H.label));
+ if ( not thomas.good() )
+ continue;
+
+ while ( !thomas.eof() ) {
+ size_t aa = (size_t)-1, az = (size_t)-1;
+ thomas >> aa >> az;
+ if ( aa == (size_t)-1 || az == (size_t)-1 )
+ break;
+ H.artifacts.mark_artifact( aa, az);
}
}
- H.annotations.sort();
- }
- // filters
- {
- ifstream thomas (make_fname_filters(fname_));
- if ( !thomas.fail() )
- for ( auto &I : channels ) {
- int ol = -1, oh = -1, nf = -1;
- float fl = 0., fh = 0.;
- thomas >> fl >> ol
- >> fh >> oh >> nf;
- if ( ol > 0 && oh > 0 && ol < 5 && oh < 5
- && fl >= 0. && fh >= 0.
- && nf >= 0 && nf <= 2 ) {
- I.filters.low_pass_cutoff = fl;
- I.filters.low_pass_order = ol;
- I.filters.high_pass_cutoff = fh;
- I.filters.high_pass_order = oh;
- I.filters.notch_filter = (SFilterPack::TNotchFilter)nf;
+ // 2. annotations, per signal
+ for ( auto &H : channels ) {
+ ifstream fd (make_fname_annotations( H.label));
+ if ( not fd.good() )
+ continue;
+ int type = -1;
+ size_t aa = -1, az = -1;
+ string an;
+ while ( fd.good() and not fd.eof() ) {
+ fd >> type >> aa >> az;
+ getline( fd, an, EOA);
+ if ( aa < az and az < n_data_records * H.samples_per_record
+ and type < SAnnotation::TType_total and type >= 0 )
+ H.annotations.emplace_back(
+ aa, az,
+ agh::str::trim(an),
+ (SAnnotation::TType)type);
+ else {
+ fprintf( stderr, "Bad annotation: (%d %zu %zu %50s)\n", type, aa, az, an.c_str());
+ break;
}
}
+ H.annotations.sort();
+ }
+
+ // 3. filters
+ {
+ ifstream thomas (make_fname_filters(fname_));
+ if ( !thomas.fail() )
+ for ( auto &I : channels ) {
+ int ol = -1, oh = -1, nf = -1;
+ float fl = 0., fh = 0.;
+ thomas >> fl >> ol
+ >> fh >> oh >> nf;
+ if ( ol > 0 && oh > 0 && ol < 5 && oh < 5
+ && fl >= 0. && fh >= 0.
+ && nf >= 0 && nf <= 2 ) {
+ I.filters.low_pass_cutoff = fl;
+ I.filters.low_pass_order = ol;
+ I.filters.high_pass_cutoff = fh;
+ I.filters.high_pass_order = oh;
+ I.filters.notch_filter = (SFilterPack::TNotchFilter)nf;
+ }
+ }
+ }
}
}
@@ -857,6 +880,8 @@ string
sigfile::CEDFFile::explain_edf_status( int status)
{
list<string> recv;
+ if ( status & sysfail )
+ recv.emplace_back( "* stat or fopen error");
if ( status & bad_header )
recv.emplace_back( "* Ill-formed header");
if ( status & bad_version )
@@ -885,6 +910,10 @@ sigfile::CEDFFile::explain_edf_status( int status)
recv.emplace_back( "* Physical or Digital Min value greater than Max");
if ( status & too_many_channels )
recv.emplace_back( string("* Number of channels grearter than ") + to_string(max_channels));
+ if ( status & file_truncated )
+ recv.emplace_back( "* File truncated");
+ if ( status & trailing_junk )
+ recv.emplace_back( "* File has trailing junk");
return agh::str::join(recv, "\n");
}
diff --git a/src/libsigfile/edf.hh b/src/libsigfile/edf.hh
index a9a5194..e764d55 100644
--- a/src/libsigfile/edf.hh
+++ b/src/libsigfile/edf.hh
@@ -504,6 +504,9 @@ class CEDFFile
nonconforming_patient_id = (1 << 14),
missing_patient_id = (1 << 15),
invalid_subject_details = (1 << 16),
+ file_truncated = (1 << 17),
+ trailing_junk = (1 << 18),
+
inoperable = (bad_header
| bad_version
| bad_numfld
@@ -512,7 +515,8 @@ class CEDFFile
| dup_channels
| nogain
| sysfail
- | too_many_channels)
+ | too_many_channels
+ | file_truncated)
};
static string explain_edf_status( int);
--
Sleep experiment manager
More information about the debian-med-commit
mailing list