diff --git a/camlibs/ptp2/library.c b/camlibs/ptp2/library.c index 29ba9811e..ca7743cb7 100644 --- a/camlibs/ptp2/library.c +++ b/camlibs/ptp2/library.c @@ -4489,17 +4489,15 @@ camera_canon_eos_capture (Camera *camera, CameraCaptureType type, CameraFilePath case PTP_EOSEvent_ObjectTransfer: GP_LOG_D ("object transfer requested: handle 0x%x, name %s, size %lu", event.u.object.Handle, event.u.object.Filename, event.u.object.ObjectSize); - oi = event.u.object; + move(oi, event.u.object); break; case PTP_EOSEvent_ObjectRemoved: GP_LOG_D ("object removed: handle 0x%x", event.u.object.Handle); - ptp_free_objectinfo(&event.u.object); ptp_remove_object_from_cache(params, event.u.object.Handle); gp_filesystem_reset (camera->fs); break; case PTP_EOSEvent_ObjectAdded: { GP_LOG_D ("object added: handle 0x%x, name %s", event.u.object.Handle, event.u.object.Filename); - ptp_free_objectinfo(&event.u.object); /* just add it to the filesystem, and return in CameraPath */ /* We have some form of objectinfo in event.u.object already, but we let the @@ -4510,13 +4508,14 @@ camera_canon_eos_capture (Camera *camera, CameraCaptureType type, CameraFilePath if (event.u.object.ObjectFormat == PTP_OFC_Association) continue; gp_filesystem_append (camera->fs, path->folder, path->name, context); - oi = event.u.object; + move(oi, event.u.object); break; } default: GP_LOG_D ("unhandled eos event '%s'", ptp_get_eos_event_name(params, event.type)); break; } + ptp_free_eos_event(&event); /* for RAW+JPG mode capture, we just return the first image for now, and let wait_for_event get the rest. */ if (oi.Handle) break; @@ -6010,6 +6009,8 @@ camera_trigger_canon_eos_capture (Camera *camera, GPContext *context) /* Discard all collected events before starting the next capture. */ GP_LOG_D("discarding %d EOS events", params->eos_events.len); + for_each (PTPCanonEOSEvent*, pevt, params->eos_events) + ptp_free_eos_event (pevt); free_array (¶ms->eos_events); if (params->eos_camerastatus == 1) @@ -6080,6 +6081,7 @@ camera_trigger_canon_eos_capture (Camera *camera, GPContext *context) ptp_free_devicepropdesc (&dpd); } } + ptp_free_eos_event(&event); } /* We found focus information, so half way pressing has finished! */ if (in_focus) @@ -6151,6 +6153,7 @@ camera_trigger_canon_eos_capture (Camera *camera, GPContext *context) } break; } + ptp_free_eos_event(&event); } } while (!eos_m_focus_done && waiting_for_timeout (&back_off_wait, focus_start, 2*1000)); /* wait 2 seconds for focus */ /* full release now (even if the press has failed) */ @@ -6639,7 +6642,7 @@ camera_wait_for_event (Camera *camera, int timeout, case PTP_EOSEvent_ObjectTransfer: GP_LOG_D ("object transfer requested: handle 0x%x, name %s, size %lu", eos_event.u.object.Handle, eos_event.u.object.Filename, eos_event.u.object.ObjectSize); - ptp_free_objectinfo(&eos_event.u.object); + ptp_free_eos_event(&eos_event); C_MEM (path = calloc(1, sizeof(CameraFilePath))); strcpy (path->folder,"/"); @@ -6718,7 +6721,7 @@ camera_wait_for_event (Camera *camera, int timeout, return GP_OK; case PTP_EOSEvent_ObjectContentChanged: { GP_LOG_D ("object content changed: handle 0x%x", eos_event.u.object.Handle); - ptp_free_objectinfo(&eos_event.u.object); + ptp_free_eos_event(&eos_event); /* It might have gone away in the meantime */ PTPObject *ob; if (PTP_RC_OK != ptp_object_want(params, eos_event.u.object.Handle, PTPOBJECT_OBJECTINFO_LOADED, &ob)) @@ -6741,7 +6744,7 @@ camera_wait_for_event (Camera *camera, int timeout, case PTP_EOSEvent_ObjectAdded: case PTP_EOSEvent_ObjectInfoChanged: { GP_LOG_D ("object added: handle 0x%x, name %s", eos_event.u.object.Handle, eos_event.u.object.Filename); - ptp_free_objectinfo(&eos_event.u.object); + ptp_free_eos_event(&eos_event); PTPObject *ob; if ( (eos_event.type == PTP_EOSEvent_ObjectInfoChanged) && (PTP_RC_OK != ptp_object_find (params, eos_event.u.object.Handle, &ob)) @@ -6828,11 +6831,13 @@ camera_wait_for_event (Camera *camera, int timeout, GP_LOG_D ("object removed: handle 0x%x", eos_event.u.object.Handle); ptp_remove_object_from_cache(params, eos_event.u.object.Handle); gp_filesystem_reset (camera->fs); + ptp_free_eos_event(&eos_event); *eventtype = GP_EVENT_UNKNOWN; *eventdata = aprintf("ObjectRemoved"); return GP_OK; default: GP_LOG_D ("Unhandled EOS event 0x%04x", eos_event.type); + ptp_free_eos_event(&eos_event); break; } } diff --git a/camlibs/ptp2/ptp.c b/camlibs/ptp2/ptp.c index 5556b2c47..912abce98 100644 --- a/camlibs/ptp2/ptp.c +++ b/camlibs/ptp2/ptp.c @@ -2044,6 +2044,28 @@ ptp_free_objectpropdesc(PTPObjectPropDesc* opd) } } +void ptp_free_eos_event(PTPCanonEOSEvent *eos_event) +{ + /* TODO: this function only exists because of the heap allocated Filename and Keyword members of + * of PTPObjectInfo. This function needs to be called on every ptp_get_one_eos_event() result. + * There are still tons of potential memory leaks in all sorts of error paths. The only sane solution + * to this is, to make the Filename property a statically sized string (and drop Keywords, which is + * unused anyway). + */ + switch (eos_event->type) + { + case PTP_EOSEvent_ObjectAdded: + case PTP_EOSEvent_ObjectContentChanged: + case PTP_EOSEvent_ObjectInfoChanged: + case PTP_EOSEvent_ObjectRemoved: + case PTP_EOSEvent_ObjectTransfer: + ptp_free_objectinfo(&eos_event->u.object); + break; + default: + break; + } +} + /** * ptp_free_params: @@ -2069,6 +2091,9 @@ ptp_free_params (PTPParams *params) ptp_free_devicepropdesc (¶ms->canon_props[i]); } free (params->canon_props); + + for_each (PTPCanonEOSEvent*, pevt, params->eos_events) + ptp_free_eos_event (pevt); free_array (¶ms->eos_events); for (i=0;idpd_cache_len;i++) diff --git a/camlibs/ptp2/ptp.h b/camlibs/ptp2/ptp.h index 0f3e36f4e..71d5a539b 100644 --- a/camlibs/ptp2/ptp.h +++ b/camlibs/ptp2/ptp.h @@ -74,6 +74,11 @@ static inline uint32_t _post_inc(uint32_t* o, int n) #define ARRAYSIZE(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0])) +#define move(dst, src) do { \ + dst = src; \ + memset(&(src), 0, sizeof(src)); \ +} while(0) + /* The follow set of macros implements a generic array or list of TYPE. * This is basically a TYPE* pointer and a length integer. This structure * together with the typical use-cases repeats regularly throughout the @@ -4943,6 +4948,7 @@ void ptp_free_propvalue (uint16_t, PTPPropValue*); void ptp_free_deviceinfo (PTPDeviceInfo *); void ptp_free_objectinfo (PTPObjectInfo *oi); void ptp_free_object (PTPObject *oi); +void ptp_free_eos_event (PTPCanonEOSEvent *); const char *ptp_strerror (uint16_t ret, uint16_t vendor); void ptp_debug (PTPParams *params, const char *format, ...)