Skip to content

Commit 3e96e71

Browse files
Invalidate data iterators in erase() method
Another potential source of segfaults eliminated!
1 parent 90dbd5d commit 3e96e71

File tree

10 files changed

+241
-161
lines changed

10 files changed

+241
-161
lines changed

src/interface/shared/data_iterator.i

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
%noexception container_type##_iterator_base::__iter__;
3131
%noexception container_type##_iterator_base::operator==;
3232
%noexception container_type##_iterator_base::operator!=;
33+
%ignore container_type##_iterator_base::invalidate;
3334
%ignore container_type##_iterator_base::size;
3435
%ignore container_type##_iterator_base::##container_type##_iterator_base;
3536
%ignore container_type##_iterator_base::operator*;
@@ -44,13 +45,6 @@ the 'end' value and can not be dereferenced."
4445
// Creating a new iterator keeps a reference to the current one
4546
KEEP_REFERENCE(container_type##_iterator*)
4647
KEEP_REFERENCE(container_type##_iterator_base*)
47-
// Check validity of pointer before dereferencing
48-
%typemap(check) container_type##_iterator* self {
49-
if (!$1->valid() && strncmp("$symname", "delete_", 7)) {
50-
SWIG_exception_fail(SWIG_ValueError, "in method '" "$symname"
51-
"', invalid iterator cannot be dereferenced");
52-
}
53-
}
5448
// Detect end of iteration
5549
%exception container_type##_iterator_base::__next__ %{
5650
$action
@@ -96,6 +90,8 @@ public:
9690
return "iterator<end>";
9791
}
9892
bool valid() { return ptr != end; }
93+
// Provide C++ method to invalidate iterator
94+
void invalidate() { ptr = end; }
9995
// Provide size() C++ method for buffer size check
10096
size_t size() {
10197
if (valid())
@@ -114,34 +110,47 @@ public:
114110

115111
// Declare typemaps for data iterators.
116112
%define DATA_ITERATOR_TYPEMAPS(container_type)
117-
%typemap(in) Exiv2::container_type::iterator {
118-
container_type##_iterator_base *argp = NULL;
119-
int res = SWIG_ConvertPtr($input, (void**)&argp,
120-
$descriptor(container_type##_iterator_base*), 0);
121-
if (!SWIG_IsOK(res)) {
122-
%argument_fail(res,
123-
container_type##_iterator_base, $symname, $argnum);
113+
%typemap(in) Exiv2::container_type::iterator
114+
(container_type##_iterator_base *argp=NULL) %{
115+
{
116+
container_type##_iterator_base* arg$argnum = NULL;
117+
$typemap(in, container_type##_iterator_base*)
118+
argp = arg$argnum;
124119
}
125-
if (!argp) {
126-
%argument_nullref(container_type##_iterator_base, $symname, $argnum);
120+
$1 = **argp;
121+
%}
122+
// erase() invalidates the iterator
123+
%typemap(in) (Exiv2::container_type::iterator pos)
124+
(container_type##_iterator_base *argp=NULL),
125+
(Exiv2::container_type::iterator beg)
126+
(container_type##_iterator_base *argp=NULL) {
127+
{
128+
container_type##_iterator_base* arg$argnum = NULL;
129+
$typemap(in, container_type##_iterator_base*)
130+
argp = arg$argnum;
127131
}
128132
$1 = **argp;
133+
argp->invalidate();
129134
}
130135
// XmpData::eraseFamily takes an iterator reference (and invalidates it)
131136
%typemap(in) Exiv2::container_type::iterator&
132-
(Exiv2::container_type::iterator it) {
133-
container_type##_iterator_base* argp = NULL;
134-
int res = SWIG_ConvertPtr($input, (void**)&argp,
135-
$descriptor(container_type##_iterator_base*), 0);
136-
if (!SWIG_IsOK(res)) {
137-
%argument_fail(res,
138-
container_type##_iterator_base, $symname, $argnum);
139-
}
140-
if (!argp) {
141-
%argument_nullref(container_type##_iterator_base, $symname, $argnum);
137+
(Exiv2::container_type::iterator it,
138+
container_type##_iterator_base* argp = NULL) {
139+
{
140+
container_type##_iterator_base* arg$argnum = NULL;
141+
$typemap(in, container_type##_iterator_base*)
142+
argp = arg$argnum;
142143
}
143144
it = **argp;
144145
$1 = &it;
146+
argp->invalidate();
147+
}
148+
// Check validity of pointer before dereferencing
149+
%typemap(check) container_type##_iterator* self {
150+
if (!$1->valid() && strncmp("$symname", "delete_", 7)) {
151+
SWIG_exception_fail(SWIG_ValueError, "in method '" "$symname"
152+
"', invalid iterator cannot be dereferenced");
153+
}
145154
}
146155
// Return types depend on validity of iterator
147156
%typemap(out) container_type##_iterator_base* {

src/swig-0_27_7/exif_wrap.cxx

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4414,6 +4414,8 @@ class ExifData_iterator_base {
44144414
return "iterator<end>";
44154415
}
44164416
bool valid() { return ptr != end; }
4417+
// Provide C++ method to invalidate iterator
4418+
void invalidate() { ptr = end; }
44174419
// Provide size() C++ method for buffer size check
44184420
size_t size() {
44194421
if (valid())
@@ -9632,6 +9634,9 @@ SWIGINTERN PyObject *_wrap_ExifData_erase__SWIG_0(PyObject *self, PyObject *args
96329634
SwigValueWrapper< std::list< Exiv2::Exifdatum >::iterator > arg2 ;
96339635
void *argp1 = 0 ;
96349636
int res1 = 0 ;
9637+
ExifData_iterator_base *argp2 = NULL ;
9638+
void *argp10 = 0 ;
9639+
int res10 = 0 ;
96359640
PyObject * obj1 = 0 ;
96369641
SwigValueWrapper< std::list< Exiv2::Exifdatum >::iterator > result;
96379642

@@ -9642,17 +9647,17 @@ SWIGINTERN PyObject *_wrap_ExifData_erase__SWIG_0(PyObject *self, PyObject *args
96429647
}
96439648
arg1 = reinterpret_cast< Exiv2::ExifData * >(argp1);
96449649
{
9645-
ExifData_iterator_base *argp = NULL;
9646-
int res = SWIG_ConvertPtr(obj1, (void**)&argp,
9647-
SWIGTYPE_p_ExifData_iterator_base, 0);
9648-
if (!SWIG_IsOK(res)) {
9649-
SWIG_exception_fail(SWIG_ArgError(res), "in method '" "ExifData_erase" "', argument " "2"" of type '" "ExifData_iterator_base""'")
9650-
;
9651-
}
9652-
if (!argp) {
9653-
SWIG_exception_fail(SWIG_NullReferenceError, "invalid null reference " "in method '" "ExifData_erase" "', argument " "2"" of type '" "ExifData_iterator_base""'");
9650+
{
9651+
ExifData_iterator_base* arg2 = NULL;
9652+
res10 = SWIG_ConvertPtr(obj1, &argp10,SWIGTYPE_p_ExifData_iterator_base, 0 | 0 );
9653+
if (!SWIG_IsOK(res10)) {
9654+
SWIG_exception_fail(SWIG_ArgError(res10), "in method '" "ExifData_erase" "', argument " "1"" of type '" "ExifData_iterator_base *""'");
9655+
}
9656+
arg2 = reinterpret_cast< ExifData_iterator_base * >(argp10);
9657+
argp2 = arg2;
96549658
}
9655-
arg2 = **argp;
9659+
arg2 = **argp2;
9660+
argp2->invalidate();
96569661
}
96579662
{
96589663
try {
@@ -9689,6 +9694,12 @@ SWIGINTERN PyObject *_wrap_ExifData_erase__SWIG_1(PyObject *self, PyObject *args
96899694
SwigValueWrapper< std::list< Exiv2::Exifdatum >::iterator > arg3 ;
96909695
void *argp1 = 0 ;
96919696
int res1 = 0 ;
9697+
ExifData_iterator_base *argp2 = NULL ;
9698+
void *argp10 = 0 ;
9699+
int res10 = 0 ;
9700+
ExifData_iterator_base *argp3 = NULL ;
9701+
void *argp11 = 0 ;
9702+
int res11 = 0 ;
96929703
PyObject * obj1 = 0 ;
96939704
PyObject * obj2 = 0 ;
96949705
SwigValueWrapper< std::list< Exiv2::Exifdatum >::iterator > result;
@@ -9700,31 +9711,30 @@ SWIGINTERN PyObject *_wrap_ExifData_erase__SWIG_1(PyObject *self, PyObject *args
97009711
}
97019712
arg1 = reinterpret_cast< Exiv2::ExifData * >(argp1);
97029713
{
9703-
ExifData_iterator_base *argp = NULL;
9704-
int res = SWIG_ConvertPtr(obj1, (void**)&argp,
9705-
SWIGTYPE_p_ExifData_iterator_base, 0);
9706-
if (!SWIG_IsOK(res)) {
9707-
SWIG_exception_fail(SWIG_ArgError(res), "in method '" "ExifData_erase" "', argument " "2"" of type '" "ExifData_iterator_base""'")
9708-
;
9709-
}
9710-
if (!argp) {
9711-
SWIG_exception_fail(SWIG_NullReferenceError, "invalid null reference " "in method '" "ExifData_erase" "', argument " "2"" of type '" "ExifData_iterator_base""'");
9714+
{
9715+
ExifData_iterator_base* arg2 = NULL;
9716+
res10 = SWIG_ConvertPtr(obj1, &argp10,SWIGTYPE_p_ExifData_iterator_base, 0 | 0 );
9717+
if (!SWIG_IsOK(res10)) {
9718+
SWIG_exception_fail(SWIG_ArgError(res10), "in method '" "ExifData_erase" "', argument " "1"" of type '" "ExifData_iterator_base *""'");
9719+
}
9720+
arg2 = reinterpret_cast< ExifData_iterator_base * >(argp10);
9721+
argp2 = arg2;
97129722
}
9713-
arg2 = **argp;
9723+
arg2 = **argp2;
9724+
argp2->invalidate();
97149725
}
9726+
97159727
{
9716-
ExifData_iterator_base *argp = NULL;
9717-
int res = SWIG_ConvertPtr(obj2, (void**)&argp,
9718-
SWIGTYPE_p_ExifData_iterator_base, 0);
9719-
if (!SWIG_IsOK(res)) {
9720-
SWIG_exception_fail(SWIG_ArgError(res), "in method '" "ExifData_erase" "', argument " "3"" of type '" "ExifData_iterator_base""'")
9721-
;
9722-
}
9723-
if (!argp) {
9724-
SWIG_exception_fail(SWIG_NullReferenceError, "invalid null reference " "in method '" "ExifData_erase" "', argument " "3"" of type '" "ExifData_iterator_base""'");
9728+
ExifData_iterator_base* arg3 = NULL;
9729+
res11 = SWIG_ConvertPtr(obj2, &argp11,SWIGTYPE_p_ExifData_iterator_base, 0 | 0 );
9730+
if (!SWIG_IsOK(res11)) {
9731+
SWIG_exception_fail(SWIG_ArgError(res11), "in method '" "ExifData_erase" "', argument " "1"" of type '" "ExifData_iterator_base *""'");
97259732
}
9726-
arg3 = **argp;
9733+
arg3 = reinterpret_cast< ExifData_iterator_base * >(argp11);
9734+
argp3 = arg3;
97279735
}
9736+
arg3 = **argp3;
9737+
97289738
{
97299739
try {
97309740
result = (arg1)->erase(SWIG_STD_MOVE(arg2),SWIG_STD_MOVE(arg3));

src/swig-0_27_7/iptc_wrap.cxx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4403,6 +4403,8 @@ class IptcData_iterator_base {
44034403
return "iterator<end>";
44044404
}
44054405
bool valid() { return ptr != end; }
4406+
// Provide C++ method to invalidate iterator
4407+
void invalidate() { ptr = end; }
44064408
// Provide size() C++ method for buffer size check
44074409
size_t size() {
44084410
if (valid())
@@ -8685,6 +8687,9 @@ SWIGINTERN PyObject *_wrap_IptcData_erase(PyObject *self, PyObject *args) {
86858687
SwigValueWrapper< std::vector< Exiv2::Iptcdatum,std::allocator< Exiv2::Iptcdatum > >::iterator > arg2 ;
86868688
void *argp1 = 0 ;
86878689
int res1 = 0 ;
8690+
IptcData_iterator_base *argp2 = NULL ;
8691+
void *argp10 = 0 ;
8692+
int res10 = 0 ;
86888693
PyObject * obj1 = 0 ;
86898694
SwigValueWrapper< std::vector< Exiv2::Iptcdatum,std::allocator< Exiv2::Iptcdatum > >::iterator > result;
86908695

@@ -8695,17 +8700,17 @@ SWIGINTERN PyObject *_wrap_IptcData_erase(PyObject *self, PyObject *args) {
86958700
}
86968701
arg1 = reinterpret_cast< Exiv2::IptcData * >(argp1);
86978702
{
8698-
IptcData_iterator_base *argp = NULL;
8699-
int res = SWIG_ConvertPtr(obj1, (void**)&argp,
8700-
SWIGTYPE_p_IptcData_iterator_base, 0);
8701-
if (!SWIG_IsOK(res)) {
8702-
SWIG_exception_fail(SWIG_ArgError(res), "in method '" "IptcData_erase" "', argument " "2"" of type '" "IptcData_iterator_base""'")
8703-
;
8704-
}
8705-
if (!argp) {
8706-
SWIG_exception_fail(SWIG_NullReferenceError, "invalid null reference " "in method '" "IptcData_erase" "', argument " "2"" of type '" "IptcData_iterator_base""'");
8703+
{
8704+
IptcData_iterator_base* arg2 = NULL;
8705+
res10 = SWIG_ConvertPtr(obj1, &argp10,SWIGTYPE_p_IptcData_iterator_base, 0 | 0 );
8706+
if (!SWIG_IsOK(res10)) {
8707+
SWIG_exception_fail(SWIG_ArgError(res10), "in method '" "IptcData_erase" "', argument " "1"" of type '" "IptcData_iterator_base *""'");
8708+
}
8709+
arg2 = reinterpret_cast< IptcData_iterator_base * >(argp10);
8710+
argp2 = arg2;
87078711
}
8708-
arg2 = **argp;
8712+
arg2 = **argp2;
8713+
argp2->invalidate();
87098714
}
87108715
{
87118716
try {

src/swig-0_27_7/xmp_wrap.cxx

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4405,6 +4405,8 @@ class XmpData_iterator_base {
44054405
return "iterator<end>";
44064406
}
44074407
bool valid() { return ptr != end; }
4408+
// Provide C++ method to invalidate iterator
4409+
void invalidate() { ptr = end; }
44084410
// Provide size() C++ method for buffer size check
44094411
size_t size() {
44104412
if (valid())
@@ -8527,6 +8529,9 @@ SWIGINTERN PyObject *_wrap_XmpData_erase(PyObject *self, PyObject *args) {
85278529
SwigValueWrapper< std::vector< Exiv2::Xmpdatum,std::allocator< Exiv2::Xmpdatum > >::iterator > arg2 ;
85288530
void *argp1 = 0 ;
85298531
int res1 = 0 ;
8532+
XmpData_iterator_base *argp2 = NULL ;
8533+
void *argp10 = 0 ;
8534+
int res10 = 0 ;
85308535
PyObject * obj1 = 0 ;
85318536
SwigValueWrapper< std::vector< Exiv2::Xmpdatum,std::allocator< Exiv2::Xmpdatum > >::iterator > result;
85328537

@@ -8537,17 +8542,17 @@ SWIGINTERN PyObject *_wrap_XmpData_erase(PyObject *self, PyObject *args) {
85378542
}
85388543
arg1 = reinterpret_cast< Exiv2::XmpData * >(argp1);
85398544
{
8540-
XmpData_iterator_base *argp = NULL;
8541-
int res = SWIG_ConvertPtr(obj1, (void**)&argp,
8542-
SWIGTYPE_p_XmpData_iterator_base, 0);
8543-
if (!SWIG_IsOK(res)) {
8544-
SWIG_exception_fail(SWIG_ArgError(res), "in method '" "XmpData_erase" "', argument " "2"" of type '" "XmpData_iterator_base""'")
8545-
;
8546-
}
8547-
if (!argp) {
8548-
SWIG_exception_fail(SWIG_NullReferenceError, "invalid null reference " "in method '" "XmpData_erase" "', argument " "2"" of type '" "XmpData_iterator_base""'");
8545+
{
8546+
XmpData_iterator_base* arg2 = NULL;
8547+
res10 = SWIG_ConvertPtr(obj1, &argp10,SWIGTYPE_p_XmpData_iterator_base, 0 | 0 );
8548+
if (!SWIG_IsOK(res10)) {
8549+
SWIG_exception_fail(SWIG_ArgError(res10), "in method '" "XmpData_erase" "', argument " "1"" of type '" "XmpData_iterator_base *""'");
8550+
}
8551+
arg2 = reinterpret_cast< XmpData_iterator_base * >(argp10);
8552+
argp2 = arg2;
85498553
}
8550-
arg2 = **argp;
8554+
arg2 = **argp2;
8555+
argp2->invalidate();
85518556
}
85528557
{
85538558
try {
@@ -8584,6 +8589,9 @@ SWIGINTERN PyObject *_wrap_XmpData_eraseFamily(PyObject *self, PyObject *args) {
85848589
void *argp1 = 0 ;
85858590
int res1 = 0 ;
85868591
Exiv2::XmpData::iterator it2 ;
8592+
XmpData_iterator_base *argp2 = NULL ;
8593+
void *argp10 = 0 ;
8594+
int res10 = 0 ;
85878595
PyObject * obj1 = 0 ;
85888596

85898597
if (!PyArg_UnpackTuple(args, "XmpData_eraseFamily", 1, 1, &obj1)) SWIG_fail;
@@ -8593,18 +8601,18 @@ SWIGINTERN PyObject *_wrap_XmpData_eraseFamily(PyObject *self, PyObject *args) {
85938601
}
85948602
arg1 = reinterpret_cast< Exiv2::XmpData * >(argp1);
85958603
{
8596-
XmpData_iterator_base* argp = NULL;
8597-
int res = SWIG_ConvertPtr(obj1, (void**)&argp,
8598-
SWIGTYPE_p_XmpData_iterator_base, 0);
8599-
if (!SWIG_IsOK(res)) {
8600-
SWIG_exception_fail(SWIG_ArgError(res), "in method '" "XmpData_eraseFamily" "', argument " "2"" of type '" "XmpData_iterator_base""'")
8601-
;
8602-
}
8603-
if (!argp) {
8604-
SWIG_exception_fail(SWIG_NullReferenceError, "invalid null reference " "in method '" "XmpData_eraseFamily" "', argument " "2"" of type '" "XmpData_iterator_base""'");
8604+
{
8605+
XmpData_iterator_base* arg2 = NULL;
8606+
res10 = SWIG_ConvertPtr(obj1, &argp10,SWIGTYPE_p_XmpData_iterator_base, 0 | 0 );
8607+
if (!SWIG_IsOK(res10)) {
8608+
SWIG_exception_fail(SWIG_ArgError(res10), "in method '" "XmpData_eraseFamily" "', argument " "1"" of type '" "XmpData_iterator_base *""'");
8609+
}
8610+
arg2 = reinterpret_cast< XmpData_iterator_base * >(argp10);
8611+
argp2 = arg2;
86058612
}
8606-
it2 = **argp;
8613+
it2 = **argp2;
86078614
arg2 = &it2;
8615+
argp2->invalidate();
86088616
}
86098617
{
86108618
try {

0 commit comments

Comments
 (0)