From 6aa70f2fe52b410b8d6ba6d11b8e3d18c17300be Mon Sep 17 00:00:00 2001 From: abubakarsabir924-cell Date: Sun, 24 May 2026 21:27:24 -0400 Subject: [PATCH 1/7] Fix INCOMPATIBLE state check in cups_enum_dests() (Issue #1531) - Added check for _CUPS_DNSSD_INCOMPATIBLE state in enumeration loop - Store UUID in device options for comparison - Incompatible devices are now properly skipped during enumeration --- cups/dest.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cups/dest.c b/cups/dest.c index d729ae2b8..838e91404 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -3419,6 +3419,13 @@ cups_enum_dests( if ((device->type & mask) != type) device->state = _CUPS_DNSSD_INCOMPATIBLE; + + if (device->state == _CUPS_DNSSD_INCOMPATIBLE) + { + DEBUG_printf("2cups_enum_dests: Skipping incompatible '%s'.", + device->fullname); + continue; + } if (device->state == _CUPS_DNSSD_PENDING) { From cf3fd61d03f3290d4466c6ae3b0b197b802ef355 Mon Sep 17 00:00:00 2001 From: abubakarsabir924-cell Date: Tue, 26 May 2026 20:42:18 -0400 Subject: [PATCH 2/7] Fix use-after-free bug in local_dests (Issue #1531) - Properly copy local cupsd queues using calloc/memcpy instead of storing a raw pointer that gets freed - Free local_dests copy at end of cups_enum_dests() --- cups/dest.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cups/dest.c b/cups/dest.c index 838e91404..864ea9432 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -3202,7 +3202,14 @@ cups_enum_dests( num_dests = _cupsGetDests(http, IPP_OP_CUPS_GET_PRINTERS, NULL, &dests, data.type, data.mask); data.num_local = num_dests; - data.local_dests = dests; + if (num_dests > 0) + { + data.local_dests = calloc((size_t)num_dests, + sizeof(cups_dest_t)); + if (data.local_dests) + memcpy(data.local_dests, dests, + (size_t)num_dests * sizeof(cups_dest_t)); + } if (data.def_name[0]) { From c04387b7197518943ede75cb3e6b7148e6c2aea9 Mon Sep 17 00:00:00 2001 From: abubakarsabir924-cell Date: Wed, 27 May 2026 01:57:30 -0400 Subject: [PATCH 3/7] Revert "Fix use-after-free bug in local_dests (Issue #1531)" This reverts commit 9df1569073131c2c16d53460d451ca66475d154f. --- cups/dest.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/cups/dest.c b/cups/dest.c index 864ea9432..1ae21829c 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -3202,14 +3202,7 @@ cups_enum_dests( num_dests = _cupsGetDests(http, IPP_OP_CUPS_GET_PRINTERS, NULL, &dests, data.type, data.mask); data.num_local = num_dests; - if (num_dests > 0) - { - data.local_dests = calloc((size_t)num_dests, - sizeof(cups_dest_t)); - if (data.local_dests) - memcpy(data.local_dests, dests, - (size_t)num_dests * sizeof(cups_dest_t)); - } + data.local_dests = dests; if (data.def_name[0]) { @@ -3511,7 +3504,6 @@ cups_enum_dests( cupsDNSSDDelete(dnssd); cupsFreeDests(data.num_dests, data.dests); - cupsFreeDests(data.num_local, data.local_dests); cupsArrayDelete(data.devices); DEBUG_puts("1cups_enum_dests: Returning 1."); From a15637bd78fe1fa6d0fcab52d5ab6ff33222b9a4 Mon Sep 17 00:00:00 2001 From: abubakarsabir924-cell Date: Wed, 27 May 2026 02:56:44 -0400 Subject: [PATCH 4/7] Fix use-after-free in local_dests using cupsCopyDest (Issue #1531) - Initialize local_dests to NULL before DNS-SD discovery - Use cupsCopyDest() in enumeration loop for proper deep copy - Skip urn:uuid: prefix (9 chars) when comparing UUIDs - Free local_dests at all exit points --- cups/dest.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cups/dest.c b/cups/dest.c index 1ae21829c..3d617d37e 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -3201,8 +3201,8 @@ cups_enum_dests( // Get the list of local printers and pass them to the callback function... num_dests = _cupsGetDests(http, IPP_OP_CUPS_GET_PRINTERS, NULL, &dests, data.type, data.mask); - data.num_local = num_dests; - data.local_dests = dests; + data.num_local = 0; + data.local_dests = NULL; if (data.def_name[0]) { @@ -3216,6 +3216,8 @@ cups_enum_dests( for (i = num_dests, dest = dests; i > 0 && (!cancel || !*cancel); i --, dest ++) { + data.num_local = cupsCopyDest(dest, data.num_local, &data.local_dests); + cups_dest_t *user_dest; // Destination from lpoptions const char *device_uri; // Device URI @@ -3295,6 +3297,7 @@ cups_enum_dests( DEBUG_puts("1cups_enum_dests: Unable to create service browser, returning 0."); cupsFreeDests(data.num_dests, data.dests); + cupsFreeDests(data.num_local, data.local_dests); cupsArrayDelete(data.devices); return (false); @@ -3315,6 +3318,7 @@ cups_enum_dests( cupsDNSSDDelete(dnssd); cupsFreeDests(data.num_dests, data.dests); + cupsFreeDests(data.num_local, data.local_dests); cupsArrayDelete(data.devices); return (false); @@ -3326,6 +3330,7 @@ cups_enum_dests( cupsDNSSDDelete(dnssd); cupsFreeDests(data.num_dests, data.dests); + cupsFreeDests(data.num_local, data.local_dests); cupsArrayDelete(data.devices); return (false); @@ -3341,6 +3346,7 @@ cups_enum_dests( cupsDNSSDDelete(dnssd); cupsFreeDests(data.num_dests, data.dests); + cupsFreeDests(data.num_local, data.local_dests); cupsArrayDelete(data.devices); return (false); @@ -3352,6 +3358,7 @@ cups_enum_dests( cupsDNSSDDelete(dnssd); cupsFreeDests(data.num_dests, data.dests); + cupsFreeDests(data.num_local, data.local_dests); cupsArrayDelete(data.devices); return (false); @@ -3504,6 +3511,7 @@ cups_enum_dests( cupsDNSSDDelete(dnssd); cupsFreeDests(data.num_dests, data.dests); + cupsFreeDests(data.num_local, data.local_dests); cupsArrayDelete(data.devices); DEBUG_puts("1cups_enum_dests: Returning 1."); From 29d592d9cc372f92d02023233c8c85b1deed6913 Mon Sep 17 00:00:00 2001 From: abubakarsabir924-cell Date: Tue, 2 Jun 2026 01:26:43 -0400 Subject: [PATCH 5/7] scheduler/ipp: Skip temporary queue creation if permanent queue exists with same UUID When create_local_printer() is called via DNS-SD discovery, check if a permanent queue already exists with the same UUID before creating a new temporary queue. If found, reuse the existing permanent queue instead. Fixes duplicate printer queues appearing when a permanent queue is already configured for a discovered printer. Related to Issue #1531 --- scheduler/ipp.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/scheduler/ipp.c b/scheduler/ipp.c index f1e7f4537..d6424f80b 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -5500,7 +5500,6 @@ create_local_printer( send_ipp_status(con, IPP_STATUS_ERROR_FORBIDDEN, _("Only local users can create a local printer.")); return; } - /* * Check any other policy limits... */ @@ -5585,7 +5584,44 @@ create_local_printer( send_ipp_status(con, IPP_STATUS_OK, _("Printer \"%s\" already exists."), printer->name); goto add_printer_attributes; } + /* Check for existing permanent queue with same UUID */ + { + cupsd_printer_t *perm; + char req_uuid[64] = ""; + + /* Extract UUID from hostname like: UUID.local */ + const char *host_start = strstr(ptr, "://"); + if (host_start) + { + host_start += 3; + const char *dot_local = strstr(host_start, ".local"); + if (dot_local) + { + size_t ulen = (size_t)(dot_local - host_start); + if (ulen < sizeof(req_uuid)) + { + memcpy(req_uuid, host_start, ulen); + req_uuid[ulen] = '\0'; + } + } + } + + if (req_uuid[0]) + { + for (perm = (cupsd_printer_t *)cupsArrayGetFirst(Printers); perm; perm = (cupsd_printer_t *)cupsArrayGetNext(Printers)) + { + if (!perm->temporary && perm->uuid && !strcasecmp(req_uuid, perm->uuid + 9)) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "create_local_printer: FOUND MATCHING PERMANENT QUEUE: %s", perm->name); + printer = perm; + printer->state_time = time(NULL); + goto add_printer_attributes; + } + } + } } +} + /* * Create the printer... From 57f43317a71eda6d1c75cc4f4551577c86debca7 Mon Sep 17 00:00:00 2001 From: abubakarsabir924-cell Date: Tue, 2 Jun 2026 01:57:04 -0400 Subject: [PATCH 6/7] Fix segfault: add send_ipp_status before goto add_printer_attributes --- scheduler/ipp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/scheduler/ipp.c b/scheduler/ipp.c index d6424f80b..7f78eeb3d 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -5615,6 +5615,7 @@ create_local_printer( cupsdLogMessage(CUPSD_LOG_DEBUG, "create_local_printer: FOUND MATCHING PERMANENT QUEUE: %s", perm->name); printer = perm; printer->state_time = time(NULL); + send_ipp_status(con, IPP_STATUS_OK, _("Printer \"%s\" already exists."), printer->name); goto add_printer_attributes; } } From 868cef62c5e7c6d7813201a6e90c53dba63c0031 Mon Sep 17 00:00:00 2001 From: abubakarsabir924-cell Date: Fri, 5 Jun 2026 16:03:59 -0400 Subject: [PATCH 7/7] Remove UUID duplicate check from ipp.c (moved to PR #1593) --- scheduler/ipp.c | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 7f78eeb3d..76271a6da 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -5584,45 +5584,7 @@ create_local_printer( send_ipp_status(con, IPP_STATUS_OK, _("Printer \"%s\" already exists."), printer->name); goto add_printer_attributes; } - /* Check for existing permanent queue with same UUID */ - { - cupsd_printer_t *perm; - char req_uuid[64] = ""; - - /* Extract UUID from hostname like: UUID.local */ - const char *host_start = strstr(ptr, "://"); - if (host_start) - { - host_start += 3; - const char *dot_local = strstr(host_start, ".local"); - if (dot_local) - { - size_t ulen = (size_t)(dot_local - host_start); - if (ulen < sizeof(req_uuid)) - { - memcpy(req_uuid, host_start, ulen); - req_uuid[ulen] = '\0'; - } - } - } - - if (req_uuid[0]) - { - for (perm = (cupsd_printer_t *)cupsArrayGetFirst(Printers); perm; perm = (cupsd_printer_t *)cupsArrayGetNext(Printers)) - { - if (!perm->temporary && perm->uuid && !strcasecmp(req_uuid, perm->uuid + 9)) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "create_local_printer: FOUND MATCHING PERMANENT QUEUE: %s", perm->name); - printer = perm; - printer->state_time = time(NULL); - send_ipp_status(con, IPP_STATUS_OK, _("Printer \"%s\" already exists."), printer->name); - goto add_printer_attributes; - } - } - } } -} - /* * Create the printer...