From b058098fdcc5d4ed9b81fdb17f64820c0360ad48 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Mon, 8 Mar 2021 00:21:02 +0100 Subject: m + style fix + check memory allocation overflows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- TODO | 2 + fake-quartz-cg.c | 10 +++- fake-w32-gdi.c | 16 +++---- legacy.c | 2 +- libgamma.h | 36 ++++++++------- libgamma_behex_edid.c | 8 ++-- libgamma_behex_edid_lowercase.c | 4 ++ libgamma_behex_edid_uppercase.c | 4 ++ libgamma_connector_type_count.c | 6 ++- libgamma_dummy_crtc_initialise.c | 33 ++++++++++---- libgamma_dummy_internal_crtc_restore_forced.c | 9 ++-- libgamma_dummy_partition_initialise.c | 6 +-- libgamma_dummy_partition_restore.c | 2 +- libgamma_dummy_site_initialise.c | 4 ++ libgamma_dummy_site_restore.c | 2 +- libgamma_gamma_ramps16_initialise.c | 8 ++++ libgamma_gamma_ramps32_initialise.c | 8 ++++ libgamma_gamma_ramps64_initialise.c | 8 ++++ libgamma_gamma_ramps8_initialise.c | 8 ++++ libgamma_gamma_rampsd_initialise.c | 8 ++++ libgamma_gamma_rampsf_initialise.c | 8 ++++ libgamma_internal_allocated_any_ramp.c | 24 +++++++++- libgamma_internal_parse_edid.c | 2 +- libgamma_internal_translate_to_64.c | 66 +++++++++++++-------------- libgamma_internal_translated_ramp_get_.c | 17 +++++-- libgamma_internal_translated_ramp_set_.c | 17 +++++-- libgamma_linux_drm_crtc_initialise.c | 1 - libgamma_linux_drm_crtc_set_gamma_ramps16.c | 1 + libgamma_linux_drm_get_crtc_information.c | 23 ++++++---- libgamma_linux_drm_partition_initialise.c | 14 +++--- libgamma_linux_drm_site_initialise.c | 3 +- libgamma_list_methods.c | 2 +- libgamma_quartz_cg_crtc_get_gamma_rampsf.c | 4 +- libgamma_quartz_cg_partition_initialise.c | 16 +++++-- libgamma_quartz_cg_site_initialise.c | 18 ++++---- libgamma_value_of_connector_type.c | 21 +++++---- libgamma_value_of_subpixel_order.c | 21 +++++---- libgamma_w32_gdi_crtc_initialise.c | 1 - libgamma_w32_gdi_get_crtc_information.c | 7 ++- libgamma_w32_gdi_partition_initialise.c | 2 +- libgamma_x_randr_get_crtc_information.c | 31 +++++++------ libgamma_x_randr_method_capabilities.c | 2 +- libgamma_x_randr_partition_initialise.c | 31 +++++++++---- libgamma_x_randr_site_initialise.c | 2 +- libgamma_x_vidmode_get_crtc_information.c | 2 +- test.c | 34 ++++++++------ 46 files changed, 365 insertions(+), 189 deletions(-) diff --git a/TODO b/TODO index e8fcc7c..86f245e 100644 --- a/TODO +++ b/TODO @@ -8,3 +8,5 @@ Unsupported display servers: Add hotplug support. Generate librarian and pkg-config files. + +Replace use of atoi and atoll. diff --git a/fake-quartz-cg.c b/fake-quartz-cg.c index b0cc574..999609b 100644 --- a/fake-quartz-cg.c +++ b/fake-quartz-cg.c @@ -6,7 +6,8 @@ * It should by no means be used, without additional modification, as a * part of a compatibility layer. The purpose of this file is only to make * it possible to test for logical errors in Max OS X specific code on - * a GNU/Linux system under X. */ + * a Linux system under X. + */ @@ -217,7 +218,7 @@ CGGetOnlineDisplayList(uint32_t max_size, CGDirectDisplayID *restrict displays_o } /* Get the number of CRTC:s */ - crtc_count = (uint32_t)(res_reply->num_crtcs); + crtc_count = (uint32_t)res_reply->num_crtcs; /* Get the CRTC ID:s */ crtcs = xcb_randr_get_screen_resources_current_crtcs(res_reply); @@ -227,8 +228,13 @@ CGGetOnlineDisplayList(uint32_t max_size, CGDirectDisplayID *restrict displays_o * `CGDisplayRestoreColorSyncSettings` which restore the * all gamma ramps on the system to the system settnigs. */ + if (crtc_count > SIZE_MAX / sizeof(*original_ramps) / 256 / 3) { + errno = ENOMEM; + goto original_ramps_malloc_fail; + } original_ramps = malloc(crtc_count * 3 * 256 * sizeof(*original_ramps)); if (!original_ramps) { + original_ramps_malloc_fail: perror("malloc"); xcb_disconnect(connection); crtc_count = 0; diff --git a/fake-w32-gdi.c b/fake-w32-gdi.c index e5978a2..5e425f7 100644 --- a/fake-w32-gdi.c +++ b/fake-w32-gdi.c @@ -6,7 +6,8 @@ * It should by no means be used, without additional modification, as a * part of a compatibility layer. The purpose of this file is only to make * it possible to test for logical errors in Windows specific code on - * a GNU/Linux system under X. */ + * a Linux system under X. + */ @@ -291,11 +292,10 @@ SetDeviceGammaRamp(HDC hDC, LPVOID restrict lpRamp) { /* We assume that our gamma ramps are of the same size * as used by Windows GDI (we are so sloppy) */ - xcb_void_cookie_t gamma_cookie = - xcb_randr_set_crtc_gamma_checked(connection, *(xcb_randr_crtc_t *)hDC, GAMMA_RAMP_SIZE, - &((uint16_t *)lpRamp)[0 * GAMMA_RAMP_SIZE], - &((uint16_t *)lpRamp)[1 * GAMMA_RAMP_SIZE], - &((uint16_t *)lpRamp)[2 * GAMMA_RAMP_SIZE]); + uint16_t *ramp = lpRamp; + xcb_void_cookie_t gamma_cookie = xcb_randr_set_crtc_gamma_checked(connection, *(xcb_randr_crtc_t *)hDC, GAMMA_RAMP_SIZE, + &ramp[0 * GAMMA_RAMP_SIZE], &ramp[1 * GAMMA_RAMP_SIZE], + &ramp[2 * GAMMA_RAMP_SIZE]); xcb_generic_error_t *error = xcb_request_check(connection, gamma_cookie); return !error ? TRUE : FALSE; } @@ -386,8 +386,8 @@ CreateDC(LPCTSTR restrict lpszDriver, LPCTSTR restrict lpszDevice, LPCTSTR restr /* Was the index too high */ if (crtc_index >= crtc_count) { /* Disconnect and release resouces and mark that - we do not know the number of available CRTC:s - if we have not opened any monitors yet */ + * we do not know the number of available CRTC:s + * if we have not opened any monitors yet */ if (!dc_count) { xcb_disconnect(connection); free(res_reply); diff --git a/legacy.c b/legacy.c index 7e37ec3..550676d 100644 --- a/legacy.c +++ b/legacy.c @@ -62,7 +62,7 @@ libgamma_get_crtc_information(struct libgamma_crtc_information *restrict this, struct libgamma_crtc_state *restrict crtc, int32_t fields) { return libgamma_get_crtc_information__new(this, offsetof(struct libgamma_crtc_information, gamma_error) + - sizeof(this->gamma_error), crtc, (unsigned long long int)fields); + sizeof(this->gamma_error), crtc, (unsigned long long)fields); } int diff --git a/libgamma.h b/libgamma.h index c1afac6..b22f0d8 100644 --- a/libgamma.h +++ b/libgamma.h @@ -787,9 +787,9 @@ struct libgamma_method_capabilities { * * On operating systems that integrate a graphical environment * there is usually just one site. However, one systems with - * pluggable graphics, like Unix-like systems such as GNU/Linux - * and the BSD:s, there can usually be any (feasible) number of - * sites. In X.org parlance they are called displays. + * pluggable graphics, like Unix-like systems such as Linux + * and the BSD:s, there can usually be any (feasible) number + * of sites. In X.org parlance they are called displays. */ struct libgamma_site_state { /** @@ -1974,12 +1974,13 @@ const char *libgamma_const_of_connector_type(enum libgamma_connector_type); * * @param connector The name of the connector type, for example * "VGA" or "LIBGAMMA_CONNECTOR_TYPE_VGA" - * @return The connector type; for example `LIBGAMMA_CONNECTOR_TYPE_VGA` - * for "VGA" and "LIBGAMMA_CONNECTOR_TYPE_VGA"; - * `LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED` of not defined + * @param out Output parameter for the connector type, only set on success; + * for example `LIBGAMMA_CONNECTOR_TYPE_VGA` for "VGA" and + * "LIBGAMMA_CONNECTOR_TYPE_VGA"; + * @return Zero on success, `LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED` of not defined */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__, __access__(__read_only__, 1), __pure__))) -int libgamma_value_of_connector_type(const char *); /* FIXME return type */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __access__(__read_only__, 1), __access__(__write_only__, 2), __pure__))) +int libgamma_value_of_connector_type(const char *, enum libgamma_connector_type *); @@ -2014,12 +2015,13 @@ const char *libgamma_const_of_subpixel_order(enum libgamma_subpixel_order); * * @param order The name of the subpixel order, for example * "Horizontal RGB" or "LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB" - * @return The subpixel order; for example `LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB` - * for "Horizontal RGB" and "LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB"; - * `LIBGAMMA_SUBPIXEL_ORDER_NOT_RECOGNISED` of not defined + * @param out Output parameter for the subpixel order, only set on success; + * for example `LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB` for + * "Horizontal RGB" and "LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB"; + * @return Zero on success, `LIBGAMMA_SUBPIXEL_ORDER_NOT_RECOGNISED` of not defined */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__, __access__(__read_only__, 1), __pure__))) -int libgamma_value_of_subpixel_order(const char *); /* FIXME return type */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __access__(__read_only__, 1), __access__(__write_only__, 2), __pure__))) +int libgamma_value_of_subpixel_order(const char *, enum libgamma_subpixel_order *); @@ -2496,10 +2498,10 @@ char *libgamma_behex_edid_uppercase(const unsigned char *restrict, size_t); /** * Convert a raw representation of an EDID to a lowercase hexadecimal representation * - * @param edid:const unsigned char* The EDID in raw representation - * @param length:size_t The length of `edid` - * @return :char* The EDID in lowercase hexadecimal representation, - * `NULL` on allocation error, `errno` will be set accordingly + * @param edid The EDID in raw representation + * @param length The length of `edid` + * @return The EDID in lowercase hexadecimal representation, + * `NULL` on allocation error, `errno` will be set accordingly */ LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __access__(__read_only__, 1, 2)))) inline char * diff --git a/libgamma_behex_edid.c b/libgamma_behex_edid.c index 269d68f..f4dea30 100644 --- a/libgamma_behex_edid.c +++ b/libgamma_behex_edid.c @@ -5,9 +5,9 @@ /** * Convert a raw representation of an EDID to a lowercase hexadecimal representation * - * @param edid:const unsigned char* The EDID in raw representation - * @param length:size_t The length of `edid` - * @return :char* The EDID in lowercase hexadecimal representation, - * `NULL` on allocation error, `errno` will be set accordingly + * @param edid The EDID in raw representation + * @param length The length of `edid` + * @return The EDID in lowercase hexadecimal representation, + * `NULL` on allocation error, `errno` will be set accordingly */ extern inline char *libgamma_behex_edid(const unsigned char *restrict, size_t); diff --git a/libgamma_behex_edid_lowercase.c b/libgamma_behex_edid_lowercase.c index 9c4f04e..41a2563 100644 --- a/libgamma_behex_edid_lowercase.c +++ b/libgamma_behex_edid_lowercase.c @@ -17,6 +17,10 @@ libgamma_behex_edid_lowercase(const unsigned char *restrict edid, size_t length) size_t i; /* Allocate memory area for the output string */ + if (length > (SIZE_MAX / sizeof(char) - 1) / 2) { + errno = ENOMEM; + return NULL; + } out = malloc((length * 2 + 1) * sizeof(char)); if (!out) return NULL; diff --git a/libgamma_behex_edid_uppercase.c b/libgamma_behex_edid_uppercase.c index 5545aa5..4b25987 100644 --- a/libgamma_behex_edid_uppercase.c +++ b/libgamma_behex_edid_uppercase.c @@ -17,6 +17,10 @@ libgamma_behex_edid_uppercase(const unsigned char *restrict edid, size_t length) size_t i; /* Allocate memory area for the output string */ + if (length > (SIZE_MAX / sizeof(char) - 1) / 2) { + errno = ENOMEM; + return NULL; + } out = malloc((length * 2 + 1) * sizeof(char)); if (!out) return NULL; diff --git a/libgamma_connector_type_count.c b/libgamma_connector_type_count.c index dfd38ec..646fd70 100644 --- a/libgamma_connector_type_count.c +++ b/libgamma_connector_type_count.c @@ -2,8 +2,12 @@ #include "common.h" +#define X(...) +1 + /** * The number of values defined in `libgamma_connector_type_t` * in the version of the library the program is linked against */ -const int libgamma_connector_type_count = LIBGAMMA_CONNECTOR_TYPE_COUNT; +const int libgamma_connector_type_count = LIST_CONNECTOR_TYPES(X); + +#undef X diff --git a/libgamma_dummy_crtc_initialise.c b/libgamma_dummy_crtc_initialise.c index a3f9c87..7b36b86 100644 --- a/libgamma_dummy_crtc_initialise.c +++ b/libgamma_dummy_crtc_initialise.c @@ -35,15 +35,32 @@ libgamma_dummy_crtc_initialise(struct libgamma_crtc_state *restrict this, else stop_size = (size_t)data->info.gamma_depth / 8; - data->gamma_red = malloc(data->info.red_gamma_size * stop_size); - if (!data->gamma_red) - goto fail; - data->gamma_green = malloc(data->info.green_gamma_size * stop_size); - if (!data->gamma_green) - goto fail; - data->gamma_blue = malloc(data->info.blue_gamma_size * stop_size); - if (!data->gamma_blue) + data->gamma_red = NULL; + data->gamma_green = NULL; + data->gamma_blue = NULL; + + if (data->info.red_gamma_size > SIZE_MAX / stop_size || + data->info.green_gamma_size > SIZE_MAX / stop_size || + data->info.blue_gamma_size > SIZE_MAX / stop_size) { + errno = ENOMEM; goto fail; + } + + if (data->info.red_gamma_size) { + data->gamma_red = malloc(data->info.red_gamma_size * stop_size); + if (!data->gamma_red) + goto fail; + } + if (data->info.green_gamma_size) { + data->gamma_green = malloc(data->info.green_gamma_size * stop_size); + if (!data->gamma_green) + goto fail; + } + if (data->info.blue_gamma_size) { + data->gamma_blue = malloc(data->info.blue_gamma_size * stop_size); + if (!data->gamma_blue) + goto fail; + } return libgamma_dummy_internal_crtc_restore_forced(data); diff --git a/libgamma_dummy_internal_crtc_restore_forced.c b/libgamma_dummy_internal_crtc_restore_forced.c index a3c460f..fd23e72 100644 --- a/libgamma_dummy_internal_crtc_restore_forced.c +++ b/libgamma_dummy_internal_crtc_restore_forced.c @@ -17,6 +17,9 @@ libgamma_dummy_internal_crtc_restore_forced(struct libgamma_dummy_crtc *restrict size_t rn = data->info. red_gamma_size; size_t gn = data->info.green_gamma_size; size_t bn = data->info. blue_gamma_size; + double rm = (double)(rn - 1); + double gm = (double)(gn - 1); + double bm = (double)(bn - 1); size_t i; if (!data->gamma_red) @@ -27,9 +30,9 @@ libgamma_dummy_internal_crtc_restore_forced(struct libgamma_dummy_crtc *restrict TYPE *red = data->gamma_red;\ TYPE *green = data->gamma_green;\ TYPE *blue = data->gamma_blue;\ - for (i = 0; i < rn; i++) red [i] = (TYPE)((double)(MAX) * ((double)i / (double)(rn - 1)));\ - for (i = 0; i < gn; i++) green[i] = (TYPE)((double)(MAX) * ((double)i / (double)(gn - 1)));\ - for (i = 0; i < bn; i++) blue [i] = (TYPE)((double)(MAX) * ((double)i / (double)(bn - 1)));\ + for (i = 0; i < rn; i++) red [i] = (TYPE)((double)(MAX) * ((double)i / rm));\ + for (i = 0; i < gn; i++) green[i] = (TYPE)((double)(MAX) * ((double)i / gm));\ + for (i = 0; i < bn; i++) blue [i] = (TYPE)((double)(MAX) * ((double)i / bm));\ } while (0) if (data->info.gamma_depth == 8) RESET_RAMPS(uint8_t, INT8_MAX); diff --git a/libgamma_dummy_partition_initialise.c b/libgamma_dummy_partition_initialise.c index 2557413..e8f3834 100644 --- a/libgamma_dummy_partition_initialise.c +++ b/libgamma_dummy_partition_initialise.c @@ -45,11 +45,11 @@ libgamma_dummy_partition_initialise(struct libgamma_partition_state *restrict th memcpy(crtc_data->info.edid, template.edid, crtc_data->info.edid_length * sizeof(char)); } if (crtc_data->info.connector_name) { - n = strlen(crtc_data->info.connector_name); - crtc_data->info.connector_name = malloc((n + 1) * sizeof(char)); + n = strlen(crtc_data->info.connector_name) + 1; + crtc_data->info.connector_name = malloc(n * sizeof(char)); if (!crtc_data->info.connector_name) goto fail; - memcpy(crtc_data->info.connector_name, template.connector_name, (n + 1) * sizeof(char)); + memcpy(crtc_data->info.connector_name, template.connector_name, n * sizeof(char)); } } diff --git a/libgamma_dummy_partition_restore.c b/libgamma_dummy_partition_restore.c index b7fc4ac..fc393ee 100644 --- a/libgamma_dummy_partition_restore.c +++ b/libgamma_dummy_partition_restore.c @@ -22,7 +22,7 @@ libgamma_dummy_partition_restore(struct libgamma_partition_state *restrict this) } for (i = 0; i < data->crtc_count; i++) - if (libgamma_dummy_internal_crtc_restore_forced(data->crtcs + i) < 0) + if (libgamma_dummy_internal_crtc_restore_forced(data->crtcs + i)) return -1; return 0; diff --git a/libgamma_dummy_site_initialise.c b/libgamma_dummy_site_initialise.c index 1eb617e..ae79ccc 100644 --- a/libgamma_dummy_site_initialise.c +++ b/libgamma_dummy_site_initialise.c @@ -45,6 +45,10 @@ libgamma_dummy_site_initialise(struct libgamma_site_state *restrict this, char * if (!libgamma_dummy_internal_configurations.capabilities.multiple_crtcs) crtcs = !!crtcs; + if (data->partition_count * sizeof(*data->partitions)) { + errno = ENOMEM; + goto fail; + } data->partitions = malloc(data->partition_count * sizeof(*data->partitions)); if (!data->partitions) goto fail; diff --git a/libgamma_dummy_site_restore.c b/libgamma_dummy_site_restore.c index 0e8a7a5..97db77c 100644 --- a/libgamma_dummy_site_restore.c +++ b/libgamma_dummy_site_restore.c @@ -23,7 +23,7 @@ libgamma_dummy_site_restore(struct libgamma_site_state *restrict this) for (j = 0; j < data->partition_count; j++) for (i = 0; i < data->partitions[j].crtc_count; i++) - if (libgamma_dummy_internal_crtc_restore_forced(data->partitions[j].crtcs + i) < 0) + if (libgamma_dummy_internal_crtc_restore_forced(data->partitions[j].crtcs + i)) return -1; return 0; diff --git a/libgamma_gamma_ramps16_initialise.c b/libgamma_gamma_ramps16_initialise.c index 08d242b..63823fd 100644 --- a/libgamma_gamma_ramps16_initialise.c +++ b/libgamma_gamma_ramps16_initialise.c @@ -16,6 +16,14 @@ int libgamma_gamma_ramps16_initialise(struct libgamma_gamma_ramps16 *restrict this) { size_t n = this->red_size + this->green_size + this->blue_size; + if (!n) { + this->red = this->green = this->blue = NULL; + return 0; + } + if (n > SIZE_MAX / sizeof(*this->red)) { + errno = ENOMEM; + return -1; + } #ifdef HAVE_LIBGAMMA_METHOD_LINUX_DRM /* Valgrind complains about us reading uninitialize memory if we just use malloc */ this->red = calloc(n, sizeof(*this->red)); diff --git a/libgamma_gamma_ramps32_initialise.c b/libgamma_gamma_ramps32_initialise.c index 1134c8d..dc1006a 100644 --- a/libgamma_gamma_ramps32_initialise.c +++ b/libgamma_gamma_ramps32_initialise.c @@ -16,6 +16,14 @@ int libgamma_gamma_ramps32_initialise(struct libgamma_gamma_ramps32 *restrict this) { size_t n = this->red_size + this->green_size + this->blue_size; + if (!n) { + this->red = this->green = this->blue = NULL; + return 0; + } + if (n > SIZE_MAX / sizeof(*this->red)) { + errno = ENOMEM; + return -1; + } this->red = malloc(n * sizeof(*this->red)); this->green = &this-> red[this-> red_size]; this->blue = &this->green[this->green_size]; diff --git a/libgamma_gamma_ramps64_initialise.c b/libgamma_gamma_ramps64_initialise.c index 9580028..1fa9962 100644 --- a/libgamma_gamma_ramps64_initialise.c +++ b/libgamma_gamma_ramps64_initialise.c @@ -16,6 +16,14 @@ int libgamma_gamma_ramps64_initialise(struct libgamma_gamma_ramps64 *restrict this) { size_t n = this->red_size + this->green_size + this->blue_size; + if (!n) { + this->red = this->green = this->blue = NULL; + return 0; + } + if (n > SIZE_MAX / sizeof(*this->red)) { + errno = ENOMEM; + return -1; + } this->red = malloc(n * sizeof(*this->red)); this->green = &this-> red[this-> red_size]; this->blue = &this->green[this->green_size]; diff --git a/libgamma_gamma_ramps8_initialise.c b/libgamma_gamma_ramps8_initialise.c index 04bf465..6434707 100644 --- a/libgamma_gamma_ramps8_initialise.c +++ b/libgamma_gamma_ramps8_initialise.c @@ -16,6 +16,14 @@ int libgamma_gamma_ramps8_initialise(struct libgamma_gamma_ramps8 *restrict this) { size_t n = this->red_size + this->green_size + this->blue_size; + if (!n) { + this->red = this->green = this->blue = NULL; + return 0; + } + if (n > SIZE_MAX / sizeof(*this->red)) { + errno = ENOMEM; + return -1; + } this->red = malloc(n * sizeof(*this->red)); this->green = &this-> red[this-> red_size]; this->blue = &this->green[this->green_size]; diff --git a/libgamma_gamma_rampsd_initialise.c b/libgamma_gamma_rampsd_initialise.c index f3ca3ef..df7cee2 100644 --- a/libgamma_gamma_rampsd_initialise.c +++ b/libgamma_gamma_rampsd_initialise.c @@ -16,6 +16,14 @@ int libgamma_gamma_rampsd_initialise(struct libgamma_gamma_rampsd *restrict this) { size_t n = this->red_size + this->green_size + this->blue_size; + if (!n) { + this->red = this->green = this->blue = NULL; + return 0; + } + if (n > SIZE_MAX / sizeof(*this->red)) { + errno = ENOMEM; + return -1; + } this->red = malloc(n * sizeof(*this->red)); this->green = &this-> red[this-> red_size]; this->blue = &this->green[this->green_size]; diff --git a/libgamma_gamma_rampsf_initialise.c b/libgamma_gamma_rampsf_initialise.c index 0937bc7..5cd9290 100644 --- a/libgamma_gamma_rampsf_initialise.c +++ b/libgamma_gamma_rampsf_initialise.c @@ -16,6 +16,14 @@ int libgamma_gamma_rampsf_initialise(struct libgamma_gamma_rampsf *restrict this) { size_t n = this->red_size + this->green_size + this->blue_size; + if (!n) { + this->red = this->green = this->blue = NULL; + return 0; + } + if (n > SIZE_MAX / sizeof(*this->red)) { + errno = ENOMEM; + return -1; + } this->red = malloc(n * sizeof(*this->red)); this->green = &this-> red[this-> red_size]; this->blue = &this->green[this->green_size]; diff --git a/libgamma_internal_allocated_any_ramp.c b/libgamma_internal_allocated_any_ramp.c index afb128c..c9dbe3e 100644 --- a/libgamma_internal_allocated_any_ramp.c +++ b/libgamma_internal_allocated_any_ramp.c @@ -24,7 +24,17 @@ libgamma_internal_allocated_any_ramp(union gamma_ramps_any *restrict ramps_sys, signed depth, size_t *restrict elements) { /* Calculate the size of the allocation to do */ - size_t d, n = ramps->ANY.red_size + ramps->ANY.green_size + ramps->ANY.blue_size; + size_t d, n = ramps->ANY.red_size; + if (n > SIZE_MAX - ramps->ANY.green_size) { + goto enomem; + } + n += ramps->ANY.green_size; + if (n > SIZE_MAX - ramps->ANY.blue_size) { + enomem: + errno = ENOMEM; + return LIBGAMMA_ERRNO_SET; + } + n += ramps->ANY.blue_size; switch (depth) { case 8: d = sizeof(uint8_t); break; case 16: d = sizeof(uint16_t); break; @@ -33,16 +43,26 @@ libgamma_internal_allocated_any_ramp(union gamma_ramps_any *restrict ramps_sys, case -1: d = sizeof(float); break; case -2: d = sizeof(double); break; default: - return errno = EINVAL, LIBGAMMA_ERRNO_SET; + errno = EINVAL; + return LIBGAMMA_ERRNO_SET; } /* Copy the gamma ramp sizes */ ramps_sys->ANY = ramps->ANY; /* Allocate the new ramps */ + if (!n) { + ramps_sys->ANY.red = NULL; + ramps_sys->ANY.green = NULL; + ramps_sys->ANY.blue = NULL; + *elements = n; + return 0; + } #ifdef HAVE_LIBGAMMA_METHOD_LINUX_DRM /* Valgrind complains about us reading uninitialize memory if we just use malloc */ ramps_sys->ANY.red = calloc(n, d); #else + if (n > SIZE_MAX / d) + goto enomem; ramps_sys->ANY.red = malloc(n * d); #endif ramps_sys->ANY.green = (void *)&((char *)ramps_sys->ANY. red)[ramps->ANY. red_size * d / sizeof(char)]; diff --git a/libgamma_internal_parse_edid.c b/libgamma_internal_parse_edid.c index 9c8a84f..05d34a8 100644 --- a/libgamma_internal_parse_edid.c +++ b/libgamma_internal_parse_edid.c @@ -84,7 +84,7 @@ libgamma_internal_parse_edid(struct libgamma_crtc_information *restrict this, un blue_x = (uint16_t)((((uint16_t)this->edid[26] >> 6) & 2) | ((uint16_t)this->edid[31] << 2)); blue_y = (uint16_t)((((uint16_t)this->edid[26] >> 4) & 2) | ((uint16_t)this->edid[32] << 2)); white_x = (uint16_t)((((uint16_t)this->edid[26] >> 2) & 2) | ((uint16_t)this->edid[33] << 2)); - white_y = (uint16_t)((((uint16_t)this->edid[26] >> 6) & 2) | ((uint16_t)this->edid[34] << 2)); + white_y = (uint16_t)((((uint16_t)this->edid[26] >> 0) & 2) | ((uint16_t)this->edid[34] << 2)); /* Even though the maximum value as encoded is 1023, the values should be divided by 1024 */ this->red_chroma_x = (float)red_x / 1024.f; this->red_chroma_y = (float)red_y / 1024.f; diff --git a/libgamma_internal_translate_to_64.c b/libgamma_internal_translate_to_64.c index 24cb0ed..5452fa2 100644 --- a/libgamma_internal_translate_to_64.c +++ b/libgamma_internal_translate_to_64.c @@ -30,17 +30,17 @@ float_to_64(float value) #if defined(HAVE_INT128) && __WORDSIZE == 64 /* `__int128` is a GNU C extension, which - (because it is not ISO C) emits a warning - under -pedantic */ + * (because it is not ISO C) emits a warning + * under -pedantic */ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpedantic" /* In GCC we can use `__int128`, this is - a signed 128-bit integer. It fits all - uint64_t values but also native values, - which is a nice because it eleminates - some overflow condition tests. It is - also more readable. */ + * a signed 128-bit integer. It fits all + * uint64_t values but also native values, + * which is a nice because it eleminates + * some overflow condition tests. It is + * also more readable. */ /* Convert to integer */ __int128 product = (__int128)(value * (float)UINT64_MAX); @@ -57,22 +57,22 @@ float_to_64(float value) #else /* If we are not using GCC we cannot be - sure that we have `__int128` so we have - to use `uint64_t` and perform overflow - checkes based on the input value */ + * sure that we have `__int128` so we have + * to use `uint64_t` and perform overflow + * checkes based on the input value */ /* Convert to integer. */ uint64_t product = (uint64_t)(value * (float)UINT64_MAX); /* Negative overflow, - if the input is less than 0.5 but - the output is greater then we got - -1 when we should have gotten 0 */ + * if the input is less than 0.5 but + * the output is greater then we got + * -1 when we should have gotten 0 */ if (value < 0.1f && product > 0xF000000000000000ULL) return 0; /* Positive overflow, - if the input is greater than 0.5 - but the output is less then we got - 0 when we should have gotten ~0 */ + * if the input is greater than 0.5 + * but the output is less then we got + * 0 when we should have gotten ~0 */ else if (value > 0.9f && product < 0x1000000000000000ULL) return (uint64_t)~0; /* Did not overflow */ @@ -97,17 +97,17 @@ double_to_64(double value) #if defined(HAVE_INT128) && __WORDSIZE == 64 /* `__int128` is a GNU C extension, which - (because it is not ISO C) emits a warning - under -pedantic */ + * (because it is not ISO C) emits a warning + * under -pedantic */ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpedantic" /* In GCC we can use `__int128`, this is - a signed 128-bit integer. It fits all - uint64_t values but also native values, - which is a nice because it eleminates - some overflow condition tests. It is - also more readable. */ + * a signed 128-bit integer. It fits all + * uint64_t values but also native values, + * which is a nice because it eleminates + * some overflow condition tests. It is + * also more readable. */ /* Convert to integer */ __int128 product = (__int128)(value * (double)UINT64_MAX); @@ -124,23 +124,23 @@ double_to_64(double value) #else /* If we are not using GCC we cannot be - sure that we have `__int128` so we have - to use `uint64_t` and perform overflow - checkes based on the input value. */ + * sure that we have `__int128` so we have + * to use `uint64_t` and perform overflow + * checkes based on the input value. */ /* Convert to integer. */ uint64_t product = (uint64_t)(value * (double)UINT64_MAX); /* Negative overflow, - if the input is less than 0.5 but - the output is greater then we got - -1 when we should have gotten 0 */ + * if the input is less than 0.5 but + * the output is greater then we got + * -1 when we should have gotten 0 */ if (value < (double)0.1f && product > 0xF000000000000000ULL) product = 0; /* Positive overflow, - if the input is greater than 0.5 - but the output is less then we got - 0 when we should have gotten ~0 */ - else if ((value > (double)0.9f) && (product < 0x1000000000000000ULL)) + * if the input is greater than 0.5 + * but the output is less then we got + * 0 when we should have gotten ~0 */ + else if (value > (double)0.9f && (product < 0x1000000000000000ULL)) product = (uint64_t)~0; /* Did not overflow */ return product; diff --git a/libgamma_internal_translated_ramp_get_.c b/libgamma_internal_translated_ramp_get_.c index 852f6c9..c5f563e 100644 --- a/libgamma_internal_translated_ramp_get_.c +++ b/libgamma_internal_translated_ramp_get_.c @@ -30,7 +30,7 @@ libgamma_internal_translated_ramp_get_(struct libgamma_crtc_state *restrict this size_t n; int r; union gamma_ramps_any ramps_sys; - uint64_t *restrict ramps_full; + uint64_t *restrict ramps_full = NULL; /* Allocate ramps with proper data type */ if ((r = libgamma_internal_allocated_any_ramp(&ramps_sys, ramps, depth_system, &n))) @@ -43,10 +43,17 @@ libgamma_internal_translated_ramp_get_(struct libgamma_crtc_state *restrict this } /* Allocate intermediary ramps */ - ramps_full = malloc(n * sizeof(*ramps_full)); - if (!ramps_full) { - free(ramps_sys.ANY.red); - return LIBGAMMA_ERRNO_SET; + if (n) { + if (n > SIZE_MAX / sizeof(*ramps_full)) { + errno = ENOMEM; + free(ramps_sys.ANY.red); + return LIBGAMMA_ERRNO_SET; + } + ramps_full = malloc(n * sizeof(*ramps_full)); + if (!ramps_full) { + free(ramps_sys.ANY.red); + return LIBGAMMA_ERRNO_SET; + } } /* Translate ramps to 64-bit integers */ diff --git a/libgamma_internal_translated_ramp_set_.c b/libgamma_internal_translated_ramp_set_.c index f249e54..359193c 100644 --- a/libgamma_internal_translated_ramp_set_.c +++ b/libgamma_internal_translated_ramp_set_.c @@ -30,17 +30,24 @@ libgamma_internal_translated_ramp_set_(struct libgamma_crtc_state *restrict this size_t n; int r; union gamma_ramps_any ramps_sys; - uint64_t *restrict ramps_full; + uint64_t *restrict ramps_full = NULL; /* Allocate ramps with proper data type */ if ((r = libgamma_internal_allocated_any_ramp(&ramps_sys, ramps, depth_system, &n))) return r; /* Allocate intermediary ramps */ - ramps_full = malloc(n * sizeof(*ramps_full)); - if (!ramps_full) { - free(ramps_sys.ANY.red); - return LIBGAMMA_ERRNO_SET; + if (n) { + if (n > SIZE_MAX / sizeof(*ramps_full)) { + errno = ENOMEM; + free(ramps_sys.ANY.red); + return LIBGAMMA_ERRNO_SET; + } + ramps_full = malloc(n * sizeof(*ramps_full)); + if (!ramps_full) { + free(ramps_sys.ANY.red); + return LIBGAMMA_ERRNO_SET; + } } /* Translate ramps to 64-bit integers. */ diff --git a/libgamma_linux_drm_crtc_initialise.c b/libgamma_linux_drm_crtc_initialise.c index e047ad6..a9320ad 100644 --- a/libgamma_linux_drm_crtc_initialise.c +++ b/libgamma_linux_drm_crtc_initialise.c @@ -17,7 +17,6 @@ libgamma_linux_drm_crtc_initialise(struct libgamma_crtc_state *restrict this, struct libgamma_partition_state *restrict partition, size_t crtc) { struct libgamma_drm_card_data *restrict card = partition->data; - if (crtc >= partition->crtcs_available) return LIBGAMMA_NO_SUCH_CRTC; this->data = (void *)(size_t)card->res->crtcs[crtc]; diff --git a/libgamma_linux_drm_crtc_set_gamma_ramps16.c b/libgamma_linux_drm_crtc_set_gamma_ramps16.c index a150029..3d0c983 100644 --- a/libgamma_linux_drm_crtc_set_gamma_ramps16.c +++ b/libgamma_linux_drm_crtc_set_gamma_ramps16.c @@ -17,6 +17,7 @@ libgamma_linux_drm_crtc_set_gamma_ramps16(struct libgamma_crtc_state *restrict t { struct libgamma_drm_card_data *restrict card = this->partition->data; int r; + #ifdef DEBUG /* Gamma ramp sizes are identical but not fixed */ if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) diff --git a/libgamma_linux_drm_get_crtc_information.c b/libgamma_linux_drm_get_crtc_information.c index a476878..683fa0e 100644 --- a/libgamma_linux_drm_get_crtc_information.c +++ b/libgamma_linux_drm_get_crtc_information.c @@ -20,7 +20,7 @@ find_connector(struct libgamma_crtc_state *restrict this, int *restrict error) /* Open connectors and encoders if not already opened */ if (!card->connectors) { /* Allocate connector and encoder arrays; we use `calloc` - so all non-loaded elements are `NULL` after an error */ + * so all non-loaded elements are `NULL` after an error */ card->connectors = calloc(n, sizeof(drmModeConnector *)); if (!card->connectors) goto fail; @@ -34,8 +34,8 @@ find_connector(struct libgamma_crtc_state *restrict this, int *restrict error) if (!card->connectors[i]) goto fail; /* Get encoder if the connector is enabled. If it is disabled it - will not have an encoder, which is indicated by the encoder - ID being 0. In such case, leave the encoder to be `NULL`. */ + * will not have an encoder, which is indicated by the encoder + * ID being 0. In such case, leave the encoder to be `NULL`. */ if (card->connectors[i]->encoder_id) { card->encoders[i] = drmModeGetEncoder(card->fd, card->connectors[i]->encoder_id); if (!card->encoders[i]) @@ -55,7 +55,7 @@ find_connector(struct libgamma_crtc_state *restrict this, int *restrict error) fail: /* Report the error that got us here, release - resouces and exit with `NULL` for failure */ + * resouces and exit with `NULL` for failure */ *error = errno; libgamma_linux_drm_internal_release_connectors_and_encoders(card); return NULL; @@ -194,7 +194,7 @@ read_connector_data(struct libgamma_crtc_state *restrict crtc, struct libgamma_c const char *connector_name_base = NULL; struct libgamma_drm_card_data *restrict card; uint32_t type; - size_t i, n, c; + size_t i, n, c, len; /* Get some information that does not require too much work */ if (fields & (LIBGAMMA_CRTC_INFO_MACRO_ACTIVE | LIBGAMMA_CRTC_INFO_MACRO_CONNECTOR)) { @@ -227,9 +227,16 @@ read_connector_data(struct libgamma_crtc_state *restrict crtc, struct libgamma_c n = (size_t)card->res->count_connectors; /* Allocate memory for the name of the connector */ - out->connector_name = malloc((strlen(connector_name_base) + 12) * sizeof(char)); - if (!out->connector_name) + len = strlen(connector_name_base); + if (len > SIZE_MAX / sizeof(char) - 12) { + errno = ENOMEM; + out->connector_name = NULL; return (out->connector_name_error = errno); + } else { + out->connector_name = malloc((len + 12) * sizeof(char)); + if (!out->connector_name) + return (out->connector_name_error = errno); + } /* Get the number of connectors with the same type on the same graphics card */ for (i = c = 0; i < n && card->connectors[i] != connector; i++) @@ -285,7 +292,7 @@ get_edid(struct libgamma_crtc_state *restrict crtc, struct libgamma_crtc_informa out->edid_error = errno; } else { /* Copy the EDID so we can free resources that got us here */ - memcpy(out->edid, blob->data, (size_t)out->edid_length * sizeof(char)); + memcpy(out->edid, blob->data, (size_t)out->edid_length * sizeof(unsigned char)); } /* Free the propriety value and the propery */ drmModeFreePropertyBlob(blob); diff --git a/libgamma_linux_drm_partition_initialise.c b/libgamma_linux_drm_partition_initialise.c index 8136cd9..5440365 100644 --- a/libgamma_linux_drm_partition_initialise.c +++ b/libgamma_linux_drm_partition_initialise.c @@ -32,7 +32,7 @@ figure_out_card_open_error(const char *pathname) return LIBGAMMA_ERRNO_SET; } - /* TODO Can this be simplified? */ + /* TODO Can this be simplified? Is this even correct? */ #define TEST(R, W) ((attr.st_mode & ((R) | (W))) == ((R) | (W))) /* Get permission requirement for the file */ @@ -45,7 +45,7 @@ figure_out_card_open_error(const char *pathname) return LIBGAMMA_DEVICE_ACCESS_FAILED; /* The group should be "video", but perhaps - it is "root" to restrict users */ + * it is "root" to restrict users */ if (!attr.st_gid /* root group */ || TEST(S_IRGRP, S_IWGRP)) return LIBGAMMA_DEVICE_RESTRICTED; @@ -56,19 +56,19 @@ figure_out_card_open_error(const char *pathname) return LIBGAMMA_ERRNO_SET; /* Test whether any of the supplemental - group should be satisfactory */ + * group should be satisfactory */ for (i = 0; i < n; i++) if (supplemental_groups[i] == attr.st_gid) break; /* If one of the supplemental groups should be satisfactory, - then we do not know anything more than that access failed */ + * then we do not know anything more than that access failed */ if (i != n) return LIBGAMMA_DEVICE_ACCESS_FAILED; /* Otherwise, try to get the name of the group that is - required and report the missing group membership */ - errno = getgrgid_r(attr.st_gid, &_grp, buf, sizeof(buf) / sizeof(char), &group); + * required and report the missing group membership */ + errno = getgrgid_r(attr.st_gid, &_grp, buf, sizeof(buf), &group); if (errno == ERANGE) { /* The lenght of the group's name is absurdly long, degrade to thread-unsafe. */ errno = 0; @@ -118,7 +118,7 @@ libgamma_linux_drm_partition_initialise(struct libgamma_partition_state *restric data->connectors = NULL; /* Get the pathname for the graphics card */ - snprintf(pathname, sizeof(pathname) / sizeof(char), DRM_DEV_NAME, DRM_DIR_NAME, (int)partition); + snprintf(pathname, sizeof(pathname), DRM_DEV_NAME, DRM_DIR_NAME, (int)partition); /* Acquire access to the graphics card */ data->fd = open(pathname, O_RDWR | O_CLOEXEC); diff --git a/libgamma_linux_drm_site_initialise.c b/libgamma_linux_drm_site_initialise.c index 9c57bd1..f6e4734 100644 --- a/libgamma_linux_drm_site_initialise.c +++ b/libgamma_linux_drm_site_initialise.c @@ -30,8 +30,7 @@ libgamma_linux_drm_site_initialise(struct libgamma_site_state *restrict this, ch this->partitions_available = 0; for (;;) { /* Construct pathname of graphics card device */ - snprintf(pathname, sizeof(pathname) / sizeof(char), - DRM_DEV_NAME, DRM_DIR_NAME, (int)(this->partitions_available)); + snprintf(pathname, sizeof(pathname), DRM_DEV_NAME, DRM_DIR_NAME, (int)this->partitions_available); /* `stat` the graphics card's existence */ if (stat(pathname, &_attr)) break; diff --git a/libgamma_list_methods.c b/libgamma_list_methods.c index 6da4f43..cca8426 100644 --- a/libgamma_list_methods.c +++ b/libgamma_list_methods.c @@ -14,7 +14,7 @@ is_vt_proper(int fd) char buf[32], digit0; /* Get TTY */ - if (ttyname_r(fd, buf, sizeof(buf) / sizeof(char))) + if (ttyname_r(fd, buf, sizeof(buf))) return 0; /* Validate TTY path */ diff --git a/libgamma_quartz_cg_crtc_get_gamma_rampsf.c b/libgamma_quartz_cg_crtc_get_gamma_rampsf.c index 3f03437..b90524d 100644 --- a/libgamma_quartz_cg_crtc_get_gamma_rampsf.c +++ b/libgamma_quartz_cg_crtc_get_gamma_rampsf.c @@ -28,8 +28,8 @@ libgamma_quartz_cg_crtc_get_gamma_rampsf(struct libgamma_crtc_state *restrict th if (r != kCGErrorSuccess) return LIBGAMMA_GAMMA_RAMP_READ_FAILED; /* I hope that it will not actually ever change, - but it does return the the gamma ramp size despite - that it can be queried without querying for more */ + * but it does return the the gamma ramp size despite + * that it can be queried without querying for more */ if (gamma_size_out != ramps->red_size) return LIBGAMMA_GAMMA_RAMP_SIZE_CHANGED; return 0; diff --git a/libgamma_quartz_cg_partition_initialise.c b/libgamma_quartz_cg_partition_initialise.c index 80fb4fc..ff77ba0 100644 --- a/libgamma_quartz_cg_partition_initialise.c +++ b/libgamma_quartz_cg_partition_initialise.c @@ -36,16 +36,24 @@ libgamma_quartz_cg_partition_initialise(struct libgamma_partition_state *restric * of CRTC:s and ask for more if we got as many as we asked for. */ for (;;) { /* Ask for CRTC ID:s */ - if (CGGetOnlineDisplayList(cap, crtcs, &n) != kCGErrorSuccess) - return free(crtcs), LIBGAMMA_LIST_CRTCS_FAILED; + if (CGGetOnlineDisplayList(cap, crtcs, &n) != kCGErrorSuccess) { + free(crtcs); + return LIBGAMMA_LIST_CRTCS_FAILED; + } /* If we did not get as many as we asked for then we have all */ if (n < cap) break; /* Increase the number CRTC ID:s to ask for */ - if (cap > UINT32_MAX / 2) /* We could also test ~0, but it is still too many */ - return free(crtcs), LIBGAMMA_IMPOSSIBLE_AMOUNT; + if (cap > UINT32_MAX / 2) { /* We could also test ~0, but it is still too many */ + free(crtcs); + return LIBGAMMA_IMPOSSIBLE_AMOUNT; + } cap <<= 1; /* Grow the array of CRTC ID:s so that it can fit all we are asking for */ + if ((size_t)cap > SIZE_MAX / sizeof(CGDirectDisplayID)) { + errno = ENOMEM; + return LIBGAMMA_ERRNO_SET; + } crtcs = realloc(crtcs_old = crtcs, (size_t)cap * sizeof(CGDirectDisplayID)); if (!crtcs) { free(crtcs_old); diff --git a/libgamma_quartz_cg_site_initialise.c b/libgamma_quartz_cg_site_initialise.c index cc47e3a..c842629 100644 --- a/libgamma_quartz_cg_site_initialise.c +++ b/libgamma_quartz_cg_site_initialise.c @@ -6,15 +6,15 @@ /** * Initialise an allocated site state * - * @param this The site state to initialise - * @param site The site identifier, unless it is `NULL` it must a - * `free`:able. Once the state is destroyed the library - * will attempt to free it. There you should not free - * it yourself, and it must not be a string constant - * or allocate on the stack. Note however that it will - * not be free:d if this function fails. - * @return Zero on success, otherwise (negative) the value of an - * error identifier provided by this library + * @param this The site state to initialise + * @param site The site identifier, unless it is `NULL` it must a + * `free`:able. Once the state is destroyed the library + * will attempt to free it. There you should not free + * it yourself, and it must not be a string constant + * or allocate on the stack. Note however that it will + * not be free:d if this function fails. + * @return Zero on success, otherwise (negative) the value of an + * error identifier provided by this library */ int libgamma_quartz_cg_site_initialise(struct libgamma_site_state *restrict this, char *restrict site) diff --git a/libgamma_value_of_connector_type.c b/libgamma_value_of_connector_type.c index 249422e..395aed0 100644 --- a/libgamma_value_of_connector_type.c +++ b/libgamma_value_of_connector_type.c @@ -7,22 +7,27 @@ * * @param connector The name of the connector type, for example * "VGA" or "LIBGAMMA_CONNECTOR_TYPE_VGA" - * @return The connector type; for example `LIBGAMMA_CONNECTOR_TYPE_VGA` - * for "VGA" and "LIBGAMMA_CONNECTOR_TYPE_VGA"; - * `LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED` of not defined + * @param out Output parameter for the connector type, only set on success; + * for example `LIBGAMMA_CONNECTOR_TYPE_VGA` for "VGA" and + * "LIBGAMMA_CONNECTOR_TYPE_VGA"; + * @return Zero on success, `LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED` of not defined */ int -libgamma_value_of_connector_type(const char *connector) +libgamma_value_of_connector_type(const char *connector, enum libgamma_connector_type *out) { #define X(CONST, NAME, ...)\ - if (!strcmp(connector, NAME))\ - return CONST; + if (!strcmp(connector, NAME)) {\ + *out = CONST;\ + return 0;\ + } LIST_CONNECTOR_TYPES(X) #undef X #define X(CONST, ...)\ - if (!strcmp(connector, #CONST))\ - return CONST; + if (!strcmp(connector, #CONST)) {\ + *out = CONST;\ + return 0;\ + } LIST_CONNECTOR_TYPES(X) #undef X diff --git a/libgamma_value_of_subpixel_order.c b/libgamma_value_of_subpixel_order.c index 33c2a6f..ed81435 100644 --- a/libgamma_value_of_subpixel_order.c +++ b/libgamma_value_of_subpixel_order.c @@ -7,22 +7,27 @@ * * @param order The name of the subpixel order, for example * "Horizontal RGB" or "LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB" - * @return The subpixel order; for example `LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB` - * for "Horizontal RGB" and "LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB"; - * `LIBGAMMA_SUBPIXEL_ORDER_NOT_RECOGNISED` of not defined + * @param out Output parameter for the subpixel order, only set on success; + * for example `LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB` for + * "Horizontal RGB" and "LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB"; + * @return Zero on success, `LIBGAMMA_SUBPIXEL_ORDER_NOT_RECOGNISED` of not defined */ int -libgamma_value_of_subpixel_order(const char *order) +libgamma_value_of_subpixel_order(const char *order, enum libgamma_subpixel_order *out) { #define X(CONST, NAME, ...)\ - if (!strcmp(order, NAME))\ - return CONST; + if (!strcmp(order, NAME)) {\ + *out = CONST;\ + return 0;\ + } LIST_SUBPIXEL_ORDERS(X) #undef X #define X(CONST, ...)\ - if (!strcmp(order, #CONST))\ - return CONST; + if (!strcmp(order, #CONST)) {\ + *out = CONST;\ + return 0;\ + } LIST_SUBPIXEL_ORDERS(X) #undef X diff --git a/libgamma_w32_gdi_crtc_initialise.c b/libgamma_w32_gdi_crtc_initialise.c index 5b75e3a..20d83ac 100644 --- a/libgamma_w32_gdi_crtc_initialise.c +++ b/libgamma_w32_gdi_crtc_initialise.c @@ -3,7 +3,6 @@ #include "common.h" - /** * Initialise an allocated CRTC state * diff --git a/libgamma_w32_gdi_get_crtc_information.c b/libgamma_w32_gdi_get_crtc_information.c index 74c9d73..9e37122 100644 --- a/libgamma_w32_gdi_get_crtc_information.c +++ b/libgamma_w32_gdi_get_crtc_information.c @@ -3,7 +3,6 @@ #include "common.h" - /** * Read information about a CRTC * @@ -36,9 +35,9 @@ libgamma_w32_gdi_get_crtc_information(struct libgamma_crtc_information *restrict this->gamma_depth = 16; this->gamma_depth_error = 0; /* It is possible to query Windows GDI whether the device - have gamma ramp support. It cannot fail. However, I think - the result is incorrect if multiple monitors are active, - so we cannot include this. */ + * have gamma ramp support. It cannot fail. However, I think + * the result is incorrect if multiple monitors are active, + * so we cannot include this. */ /* if ((fields & LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT)) this->gamma_support = GetDeviceCaps(crtc->data, COLORMGMTCAPS) == CM_GAMMA_RAMP; diff --git a/libgamma_w32_gdi_partition_initialise.c b/libgamma_w32_gdi_partition_initialise.c index 1bd3f5c..8fe8741 100644 --- a/libgamma_w32_gdi_partition_initialise.c +++ b/libgamma_w32_gdi_partition_initialise.c @@ -26,7 +26,7 @@ libgamma_w32_gdi_partition_initialise(struct libgamma_partition_state *restrict return LIBGAMMA_NO_SUCH_PARTITION; /* Count CRTC:s by iteration over all possible identifiers - until we reach on that does not exist */ + * until we reach on that does not exist */ display.cb = sizeof(DISPLAY_DEVICE); while (EnumDisplayDevices(NULL, n, &display, 0)) if (n++ == UINT32_MAX) diff --git a/libgamma_x_randr_get_crtc_information.c b/libgamma_x_randr_get_crtc_information.c index 8bf2e8f..75885e6 100644 --- a/libgamma_x_randr_get_crtc_information.c +++ b/libgamma_x_randr_get_crtc_information.c @@ -109,19 +109,19 @@ get_connector_type(struct libgamma_crtc_information *restrict this) } while (0) /* Check begin on the name of the output to find out what type the connector is of */ - SELECT ("None", Unknown); - SELECT ("VGA", VGA); - SELECT ("DVI-I", DVII); - SELECT ("DVI-D", DVID); - SELECT ("DVI-A", DVIA); - SELECT ("DVI", DVI); - SELECT ("Composite", Composite); - SELECT ("S-Video", SVIDEO); - SELECT ("Component", Component); - SELECT ("LFP", LFP); - SELECT ("Proprietary", Unknown); - SELECT ("HDMI", HDMI); - SELECT ("DisplayPort", DisplayPort); + SELECT("None", Unknown); + SELECT("VGA", VGA); + SELECT("DVI-I", DVII); + SELECT("DVI-D", DVID); + SELECT("DVI-A", DVIA); + SELECT("DVI", DVI); + SELECT("Composite", Composite); + SELECT("S-Video", SVIDEO); + SELECT("Component", Component); + SELECT("LFP", LFP); + SELECT("Proprietary", Unknown); + SELECT("HDMI", HDMI); + SELECT("DisplayPort", DisplayPort); #undef SELECT @@ -153,6 +153,11 @@ get_output_name(struct libgamma_crtc_information *restrict out, xcb_randr_get_ou return out->connector_name_error = LIBGAMMA_REPLY_VALUE_EXTRACTION_FAILED; /* Allocate a memory area for a NUL-terminated copy of the name */ + if (length > SIZE_MAX / sizeof(char) - 1) { + out->connector_name = NULL; + out->connector_name_error = errno = ENOMEM; + return -1; + } store = out->connector_name = malloc(((size_t)length + 1) * sizeof(char)); if (!store) { out->connector_name_error = errno; diff --git a/libgamma_x_randr_method_capabilities.c b/libgamma_x_randr_method_capabilities.c index 17e9b0e..7ce1c0b 100644 --- a/libgamma_x_randr_method_capabilities.c +++ b/libgamma_x_randr_method_capabilities.c @@ -13,7 +13,7 @@ libgamma_x_randr_method_capabilities(struct libgamma_method_capabilities *restri { char *display = getenv("DISPLAY"); /* Support for all information except active status and gamma ramp support. - Active status can be queried but it is not guaranteed produces an up to date result. */ + * Active status can be queried but it is not guaranteed produces an up to date result. */ this->crtc_information = LIBGAMMA_CRTC_INFO_MACRO_EDID | LIBGAMMA_CRTC_INFO_MACRO_VIEWPORT | LIBGAMMA_CRTC_INFO_MACRO_RAMP diff --git a/libgamma_x_randr_partition_initialise.c b/libgamma_x_randr_partition_initialise.c index fae2442..5c88eb6 100644 --- a/libgamma_x_randr_partition_initialise.c +++ b/libgamma_x_randr_partition_initialise.c @@ -7,13 +7,20 @@ * Duplicate a memory area * * @param ptr The memory area - * @param bytes The size, in bytes, of the memory area + * @param nelem The number of elements in the memory area + * @param size The size, in bytes, of each element * @return A duplication of the memory, `NULL` if zero-length or on error */ static inline void * -xmemdup(void *restrict ptr, size_t bytes) +duparray(void *restrict ptr, size_t nelem, size_t size) { char *restrict rc; + size_t bytes; + if (nelem > SIZE_MAX / size) { + errno = ENOMEM; + return NULL; + } + bytes = nelem * size; if (!bytes) return NULL; rc = malloc(bytes); @@ -91,18 +98,18 @@ libgamma_x_randr_partition_initialise(struct libgamma_partition_state *restrict } /* Allocate adjustment method dependent data memory area. - We use `calloc` because we want `data`'s pointers to be `NULL` if not allocated at `fail`. */ + * We use `calloc` because we want `data`'s pointers to be `NULL` if not allocated at `fail`. */ data = calloc(1, sizeof(*data)); if (!data) goto fail; /* Copy the CRTC:s, just so we do not have to keep the reply in memory */ - data->crtcs = xmemdup(crtcs, (size_t)reply->num_crtcs * sizeof(*crtcs)); + data->crtcs = duparray(crtcs, (size_t)reply->num_crtcs, sizeof(*crtcs)); if (!data->crtcs && reply->num_crtcs > 0) goto fail; /* Copy the outputs as well */ - data->outputs = xmemdup(outputs, (size_t)reply->num_outputs * sizeof(*outputs)); + data->outputs = duparray(outputs, (size_t)reply->num_outputs, sizeof(*outputs)); if (!data->outputs && reply->num_outputs > 0) goto fail; @@ -110,11 +117,17 @@ libgamma_x_randr_partition_initialise(struct libgamma_partition_state *restrict data->outputs_count = (size_t)reply->num_outputs; /* Create mapping table from CRTC indices to output indicies. (injection) */ - data->crtc_to_output = malloc((size_t)reply->num_crtcs * sizeof(*data->crtc_to_output)); - if (!data->crtc_to_output) - goto fail; + if (reply->num_crtcs) { + if (reply->num_crtcs > SIZE_MAX / sizeof(*data->crtc_to_output)) { + errno = ENOMEM; + goto fail; + } + data->crtc_to_output = malloc((size_t)reply->num_crtcs * sizeof(*data->crtc_to_output)); + if (!data->crtc_to_output) + goto fail; + } /* All CRTC:s should be mapped, but incase they are not, all unmapped CRTC:s should have - an invalid target, namely `SIZE_MAX`, which is 1 more than the theoretical limit */ + * an invalid target, namely `SIZE_MAX`, which is 1 more than the theoretical limit */ for (i = 0; i < (size_t)reply->num_crtcs; i++) data->crtc_to_output[i] = SIZE_MAX; /* Fill the table */ diff --git a/libgamma_x_randr_site_initialise.c b/libgamma_x_randr_site_initialise.c index f582748..5e2b776 100644 --- a/libgamma_x_randr_site_initialise.c +++ b/libgamma_x_randr_site_initialise.c @@ -51,7 +51,7 @@ libgamma_x_randr_site_initialise(struct libgamma_site_state *restrict this, char } /* Check protocol compatibility, - we require 1.3 but 2.x may not be backwards compatible */ + * we require 1.3 but 2.x may not be backwards compatible */ if (reply->major_version != RANDR_VERSION_MAJOR || reply->minor_version < RANDR_VERSION_MINOR) { #ifdef DEBUG /* Print used protocol */ diff --git a/libgamma_x_vidmode_get_crtc_information.c b/libgamma_x_vidmode_get_crtc_information.c index 24d35c2..f014f41 100644 --- a/libgamma_x_vidmode_get_crtc_information.c +++ b/libgamma_x_vidmode_get_crtc_information.c @@ -28,7 +28,7 @@ libgamma_x_vidmode_get_crtc_information(struct libgamma_crtc_information *restri this->height_mm_edid_error = _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID); this->gamma_size_error = 0; /* X VidMode does support gamma ramp size query. The gamma - ramps are identical but not fixed, and the query can fail. */ + * ramps are identical but not fixed, and the query can fail. */ if ((fields & LIBGAMMA_CRTC_INFO_GAMMA_SIZE)) { connection = crtc->partition->site->data; if (!XF86VidModeGetGammaRampSize(connection, (int)crtc->partition->partition, &stops)) diff --git a/test.c b/test.c index c00c5bc..2fbc897 100644 --- a/test.c +++ b/test.c @@ -335,7 +335,7 @@ select_monitor(struct libgamma_site_state *site_state, struct libgamma_partition printf(" %i: %s\n", method, method_name(method)); printf("> "); fflush(stdout); - fgets(buf, sizeof(buf) / sizeof(char), stdin); + fgets(buf, sizeof(buf), stdin); method = atoi(buf); @@ -344,7 +344,7 @@ select_monitor(struct libgamma_site_state *site_state, struct libgamma_partition /* Let the user select site */ printf("Select site: "); fflush(stdout); - fgets(buf, sizeof(buf) / sizeof(char), stdin); + fgets(buf, sizeof(buf), stdin); tmp = strchr(buf, '\n'); if (tmp) *tmp = '\0'; @@ -375,7 +375,7 @@ select_monitor(struct libgamma_site_state *site_state, struct libgamma_partition /* Let the user select partition */ printf("Select partition [0, %lu]: ", site_state->partitions_available - 1); fflush(stdout); - fgets(buf, sizeof(buf) / sizeof(char), stdin); + fgets(buf, sizeof(buf), stdin); /* Initialise partition state */ if ((r = libgamma_partition_initialise(part_state, site_state, (size_t)atoll(buf)))) { @@ -398,7 +398,7 @@ select_monitor(struct libgamma_site_state *site_state, struct libgamma_partition /* Let the user select CRTC */ printf("Select CRTC [0, %lu]: ", part_state->crtcs_available - 1); fflush(stdout); - fgets(buf, sizeof(buf) / sizeof(char), stdin); + fgets(buf, sizeof(buf), stdin); /* Initialise CRTC state. */ if ((r = libgamma_crtc_initialise(crtc_state, part_state, (size_t)atoll(buf)))) { @@ -431,7 +431,7 @@ select_monitor(struct libgamma_site_state *site_state, struct libgamma_partition char buf[256];\ if (do_print) {\ if (error) {\ - snprintf(buf, sizeof(buf) / sizeof(char), " (error) %s", description);\ + snprintf(buf, sizeof(buf), " (error) %s", description);\ libgamma_perror(buf, error);\ } else {\ printf(" %s: %" notation "\n", description, value);\ @@ -666,6 +666,7 @@ test_connector_types(void) size_t n = 0; char buf[128], *w; const char *r; + enum libgamma_connector_type type; #define X(CONST)\ do {\ @@ -685,16 +686,19 @@ test_connector_types(void) fprintf(stderr, "libgamma_const_of_connector_type(%s) != \"%s\"\n", #CONST, #CONST);\ exit(1);\ }\ - if (libgamma_value_of_connector_type(#CONST) != CONST) {\ + type = (enum libgamma_connector_type)-1;\ + if (libgamma_value_of_connector_type(#CONST, &type) || type != CONST) { \ fprintf(stderr, "libgamma_value_of_connector_type(\"%s\") != %s\n", #CONST, #CONST);\ exit(1);\ }\ - if (libgamma_value_of_connector_type(libgamma_name_of_connector_type(CONST)) != CONST) {\ + type = (enum libgamma_connector_type)-1;\ + if (libgamma_value_of_connector_type(libgamma_name_of_connector_type(CONST), &type) || type != CONST) { \ fprintf(stderr, "libgamma_value_of_connector_type(libgamma_name_of_connector_type(%s)) != %s\n",\ #CONST, #CONST);\ exit(1);\ }\ - if (libgamma_value_of_connector_type(#CONST) != CONST) {\ + type = (enum libgamma_connector_type)-1;\ + if (libgamma_value_of_connector_type(#CONST, &type) || type != CONST) { \ fprintf(stderr, "libgamma_value_of_connector_type(\"%s\") != %s\n", #CONST, #CONST);\ exit(1);\ }\ @@ -754,7 +758,7 @@ test_connector_types(void) fprintf(stderr, "libgamma_const_of_connector_type() != NULL\n"); exit(1); } - if (libgamma_value_of_connector_type("") != LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED) { + if (libgamma_value_of_connector_type("", &type) != LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED) { fprintf(stderr, "libgamma_value_of_connector_type() != LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED\n"); exit(1); } @@ -770,6 +774,7 @@ test_subpixel_orders(void) size_t n = 0; char buf[128], *w; const char *r; + enum libgamma_subpixel_order order; #define X(CONST)\ do {\ @@ -789,16 +794,19 @@ test_subpixel_orders(void) fprintf(stderr, "libgamma_const_of_subpixel_order(%s) != \"%s\"\n", #CONST, #CONST);\ exit(1);\ }\ - if (libgamma_value_of_subpixel_order(#CONST) != CONST) {\ + order = (enum libgamma_subpixel_order)-1;\ + if (libgamma_value_of_subpixel_order(#CONST, &order) || order != CONST) { \ fprintf(stderr, "libgamma_value_of_subpixel_order(\"%s\") != %s\n", #CONST, #CONST);\ exit(1);\ }\ - if (libgamma_value_of_subpixel_order(libgamma_name_of_subpixel_order(CONST)) != CONST) {\ + order = (enum libgamma_subpixel_order)-1;\ + if (libgamma_value_of_subpixel_order(libgamma_name_of_subpixel_order(CONST), &order) || order != CONST) { \ fprintf(stderr, "libgamma_value_of_subpixel_order(libgamma_name_of_subpixel_order(%s)) != %s\n",\ #CONST, #CONST);\ exit(1);\ }\ - if (libgamma_value_of_subpixel_order(#CONST) != CONST) {\ + order = (enum libgamma_subpixel_order)-1;\ + if (libgamma_value_of_subpixel_order(#CONST, &order) || order != CONST) { \ fprintf(stderr, "libgamma_value_of_subpixel_order(\"%s\") != %s\n", #CONST, #CONST);\ exit(1);\ }\ @@ -840,7 +848,7 @@ test_subpixel_orders(void) fprintf(stderr, "libgamma_const_of_subpixel_order() != NULL\n"); exit(1); } - if (libgamma_value_of_subpixel_order("") != LIBGAMMA_SUBPIXEL_ORDER_NOT_RECOGNISED) { + if (libgamma_value_of_subpixel_order("", &order) != LIBGAMMA_SUBPIXEL_ORDER_NOT_RECOGNISED) { fprintf(stderr, "libgamma_value_of_subpixel_order() != LIBGAMMA_SUBPIXEL_ORDER_NOT_RECOGNISED\n"); exit(1); } -- cgit v1.2.3-70-g09d2