summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2015-12-15 14:18:32 +0200
committerVille Syrjälä <ville.syrjala@linux.intel.com>2016-01-07 17:40:33 +0200
commite342c0fc250f3f16b817c43e96ab9b839fcb15c2 (patch)
tree4f0e67a91a5c2ca1a663e68556f0327fc5c38738
parent242f77ce03f4db371d8de3de1bef8622c0fe7488 (diff)
downloaddrm-e342c0fc250f3f16b817c43e96ab9b839fcb15c2.tar.gz
Fix memory leak with drmModeGetConnectorCurrent()
drmModeGetConnectorCurrent() must provide temporary storage for the kernel to fill in at least one mode (asking for !=0 modes is how you prevent the heavyweight probe in the kernel). Currently we malloc that temp storage but we fail to free it before overwriting the pointer with the address of the actual storage we use to store the real mode list we get from the kernel in the second ioctl call. Let's just keep the temporary storage on the stack and thus we avoid the leak and also eliminate some pointless mallocs. Cc: Chris Wilson <chris@chris-wilson.co.uk> Fixes: 5ed5fa10600f ("mode: Retrieve only the current information for a Connector") Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--xf86drmMode.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/xf86drmMode.c b/xf86drmMode.c
index ab6b5195..77100618 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -475,12 +475,13 @@ _drmModeGetConnector(int fd, uint32_t connector_id, int probe)
{
struct drm_mode_get_connector conn, counts;
drmModeConnectorPtr r = NULL;
+ struct drm_mode_modeinfo stack_mode;
memclear(conn);
conn.connector_id = connector_id;
if (!probe) {
conn.count_modes = 1;
- conn.modes_ptr = VOID2U64(drmMalloc(sizeof(struct drm_mode_modeinfo)));
+ conn.modes_ptr = VOID2U64(&stack_mode);
}
if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
@@ -504,7 +505,7 @@ retry:
goto err_allocs;
} else {
conn.count_modes = 1;
- conn.modes_ptr = VOID2U64(drmMalloc(sizeof(struct drm_mode_modeinfo)));
+ conn.modes_ptr = VOID2U64(&stack_mode);
}
if (conn.count_encoders) {
@@ -525,7 +526,8 @@ retry:
counts.count_encoders < conn.count_encoders) {
drmFree(U642VOID(conn.props_ptr));
drmFree(U642VOID(conn.prop_values_ptr));
- drmFree(U642VOID(conn.modes_ptr));
+ if (U642VOID(conn.modes_ptr) != &stack_mode)
+ drmFree(U642VOID(conn.modes_ptr));
drmFree(U642VOID(conn.encoders_ptr));
goto retry;
@@ -567,7 +569,8 @@ retry:
err_allocs:
drmFree(U642VOID(conn.prop_values_ptr));
drmFree(U642VOID(conn.props_ptr));
- drmFree(U642VOID(conn.modes_ptr));
+ if (U642VOID(conn.modes_ptr) != &stack_mode)
+ drmFree(U642VOID(conn.modes_ptr));
drmFree(U642VOID(conn.encoders_ptr));
return r;