CVE-2023-34095 (published 2023-06-14T17:15Z)

cpdb-libs provides frontend and backend libraries for the Common Printing Dialog Backends (CPDB) project. In versions 1.0 through 2.0b4, cpdb-libs is vulnerable to buffer overflows via improper use of `scanf(3)`. cpdb-libs uses the `fscanf()` and `scanf()` functions to parse command lines and configuration files, dropping the read string components into fixed-length buffers, but does not limit the length of the strings to be read by `fscanf()` and `scanf()` causing buffer overflows when a string is longer than 1023 characters. A patch for this issue is available at commit f181bd1f14757c2ae0f17cc76dc20421a40f30b7. As all buffers have a length of 1024 characters, the patch limits the maximum string length to be read to 1023 by replacing all occurrences of `%s` with `%1023s` in all calls of the `fscanf()` and `scanf()` functions.\n

CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-121
cwe_name: Stack-based Buffer Overflow
description: A stack-based buffer overflow condition is a condition where the buffer being overwritten is allocated on the stack (i.e., is a local variable or, rarely, a parameter to a function).
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/OpenPrinting/cpdb-libs
commit_details: repo_url: https://github.com/OpenPrinting/cpdb-libs
author: Till Kamppeter
author_date: 2023-06-14 18:45:28+02:00
msg: Merge pull request from GHSA-25j7-9gfc-f46x

cpdb-libs uses the fscanf() and scanf() functions to parse command
lines and configuration files, dropping the read string components
into fixed-length buffers, but does not limit the length of the
strings to be read by fscanf() and scanf() causing buffer overflows
when a string is longer than 1023 characters.

As all buffers have a length of 1024 characters we limit the maximum string
length to be read to 1023 by replaceing all occurences of "%s" by "%1023s"
in all calls of the fscanf() and scanf() functions.

Simply done by

perl -p -i -e 's/(scanf\(.*?".*?)%s/\1%1023s/' cpdb/cpdb-frontend.c tools/cpdb-text-frontend.c

and verifying with

grep scanf */*.c
repository: repo_url: https://github.com/OpenPrinting/cpdb-libs
repo_name: OpenPrinting/cpdb-libs
description: Frontend and Backend Libraries for the common printing dialog.
repo_language: C
owner: OpenPrinting
file_changes: filename: cpdb-frontend.c
change_type: ModificationType.MODIFY
diff: @@ -391,7 +391,7 @@ PrintBackend *cpdbCreateBackendFromFile(GDBusConnection *connection,
         free(path);
         return NULL;
     }
-    if (fscanf(file, "%s", obj_path) == 0)
+    if (fscanf(file, "%1023s", obj_path) == 0)
     {
         logerror("Error creating backend %s : Couldn't parse %s\n",
                     backend_name, path);

programming_language: C
filename: cpdb-text-frontend.c
change_type: ModificationType.MODIFY
diff: @@ -159,7 +159,7 @@ gpointer parse_commands(gpointer user_data)
     {
         printf("> ");
         fflush(stdout);
-        scanf("%s", buf);
+        scanf("%1023s", buf);
         if (strcmp(buf, "stop") == 0)
         {
             cpdbDeleteFrontendObj(f);
@@ -195,7 +195,7 @@ gpointer parse_commands(gpointer user_data)
         {
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
-            scanf("%s%s", printer_id, backend_name);
+            scanf("%1023s%1023s", printer_id, backend_name);
             g_message("Getting all attributes ..\n");
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
 
@@ -218,7 +218,7 @@ gpointer parse_commands(gpointer user_data)
         {
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
-            scanf("%s%s", printer_id, backend_name);
+            scanf("%1023s%1023s", printer_id, backend_name);
             g_message("Getting all attributes ..\n");
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
 
@@ -240,7 +240,7 @@ gpointer parse_commands(gpointer user_data)
         else if (strcmp(buf, "get-default") == 0)
         {
             char printer_id[BUFSIZE], backend_name[BUFSIZE], option_name[BUFSIZE];
-            scanf("%s%s%s", option_name, printer_id, backend_name);
+            scanf("%1023s%1023s%1023s", option_name, printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             char *ans = cpdbGetDefault(p, option_name);
             if (!ans)
@@ -251,7 +251,7 @@ gpointer parse_commands(gpointer user_data)
         else if (strcmp(buf, "get-setting") == 0)
         {
             char printer_id[BUFSIZE], backend_name[BUFSIZE], setting_name[BUFSIZE];
-            scanf("%s%s%s", setting_name, printer_id, backend_name);
+            scanf("%1023s%1023s%1023s", setting_name, printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             char *ans = cpdbGetSetting(p, setting_name);
             if (!ans)
@@ -262,7 +262,7 @@ gpointer parse_commands(gpointer user_data)
         else if (strcmp(buf, "get-current") == 0)
         {
             char printer_id[BUFSIZE], backend_name[BUFSIZE], option_name[BUFSIZE];
-            scanf("%s%s%s", option_name, printer_id, backend_name);
+            scanf("%1023s%1023s%1023s", option_name, printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             char *ans = cpdbGetCurrent(p, option_name);
             if (!ans)
@@ -273,7 +273,7 @@ gpointer parse_commands(gpointer user_data)
         else if (strcmp(buf, "add-setting") == 0)
         {
             char printer_id[BUFSIZE], backend_name[BUFSIZE], option_name[BUFSIZE], option_val[BUFSIZE];
-            scanf("%s %s %s %s", option_name, option_val, printer_id, backend_name);
+            scanf("%1023s %1023s %1023s %1023s", option_name, option_val, printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             printf("%s : %s\n", option_name, option_val);
             cpdbAddSettingToPrinter(p, cpdbGetStringCopy(option_name), cpdbGetStringCopy(option_val));
@@ -281,7 +281,7 @@ gpointer parse_commands(gpointer user_data)
         else if (strcmp(buf, "clear-setting") == 0)
         {
             char printer_id[BUFSIZE], backend_name[BUFSIZE], option_name[BUFSIZE];
-            scanf("%s%s%s", option_name, printer_id, backend_name);
+            scanf("%1023s%1023s%1023s", option_name, printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             cpdbClearSettingFromPrinter(p, option_name);
         }
@@ -289,7 +289,7 @@ gpointer parse_commands(gpointer user_data)
         {
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
-            scanf("%s%s", printer_id, backend_name);
+            scanf("%1023s%1023s", printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             printf("%s\n", cpdbGetState(p));
         }
@@ -297,7 +297,7 @@ gpointer parse_commands(gpointer user_data)
         {
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
-            scanf("%s%s", printer_id, backend_name);
+            scanf("%1023s%1023s", printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             printf("Accepting jobs ? : %d \n", cpdbIsAcceptingJobs(p));
         }
@@ -308,7 +308,7 @@ gpointer parse_commands(gpointer user_data)
         else if (strcmp(buf, "ping") == 0)
         {
             char printer_id[BUFSIZE], backend_name[BUFSIZE];
-            scanf("%s%s", printer_id, backend_name);
+            scanf("%1023s%1023s", printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             print_backend_call_ping_sync(p->backend_proxy, p->id, NULL, NULL);
         }
@@ -323,7 +323,7 @@ gpointer parse_commands(gpointer user_data)
         else if (strcmp(buf, "get-default-printer-for-backend") == 0)
         {
             char backend_name[BUFSIZE];
-            scanf("%s", backend_name);
+            scanf("%1023s", backend_name);
             /**
              * Backend name = The last part of the backend dbus service
              * Eg. "CUPS" or "GCP"
@@ -335,7 +335,7 @@ gpointer parse_commands(gpointer user_data)
         {
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
-            scanf("%s%s", printer_id, backend_name);
+            scanf("%1023s%1023s", printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             if (p)
             {
@@ -349,7 +349,7 @@ gpointer parse_commands(gpointer user_data)
         {
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
-            scanf("%s%s", printer_id, backend_name);
+            scanf("%1023s%1023s", printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             if (p)
             {
@@ -362,7 +362,7 @@ gpointer parse_commands(gpointer user_data)
         else if (strcmp(buf, "print-file") == 0)
         {
             char printer_id[BUFSIZE], backend_name[BUFSIZE], file_path[BUFSIZE];
-            scanf("%s%s%s", file_path, printer_id, backend_name);
+            scanf("%1023s%1023s%1023s", file_path, printer_id, backend_name);
             /**
              * Try adding some settings here .. change them and experiment
              */
@@ -372,7 +372,7 @@ gpointer parse_commands(gpointer user_data)
             {
               char final_file_path[BUFSIZE];
               printf("Please give the final file path: ");
-              scanf("%s", final_file_path);
+              scanf("%1023s", final_file_path);
               cpdbPrintFilePath(p, file_path, final_file_path);
               continue;
             }
@@ -384,7 +384,7 @@ gpointer parse_commands(gpointer user_data)
         {
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
-            scanf("%s%s", printer_id, backend_name);
+            scanf("%1023s%1023s", printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             printf("%d jobs currently active.\n", cpdbGetActiveJobsCount(p));
         }
@@ -406,7 +406,7 @@ gpointer parse_commands(gpointer user_data)
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
             char job_id[BUFSIZE];
-            scanf("%s%s%s", job_id, printer_id, backend_name);
+            scanf("%1023s%1023s%1023s", job_id, printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             if (cpdbCancelJob(p, job_id))
                 printf("cpdb_job_t %s has been cancelled.\n", job_id);
@@ -418,7 +418,7 @@ gpointer parse_commands(gpointer user_data)
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
             char job_id[BUFSIZE];
-            scanf("%s%s", printer_id, backend_name);
+            scanf("%1023s%1023s", printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             cpdbPicklePrinterToFile(p, "/tmp/.printer-pickle", f);
         }
@@ -427,7 +427,7 @@ gpointer parse_commands(gpointer user_data)
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
             char option_name[BUFSIZE];
-            scanf("%s%s%s", option_name, printer_id, backend_name);
+            scanf("%1023s%1023s%1023s", option_name, printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             printf("%s\n", cpdbGetOptionTranslation(p, option_name, locale));
         }
@@ -437,7 +437,7 @@ gpointer parse_commands(gpointer user_data)
             char backend_name[BUFSIZE];
             char option_name[BUFSIZE];
             char choice_name[BUFSIZE];
-            scanf("%s%s%s%s", option_name, choice_name, printer_id, backend_name);
+            scanf("%1023s%1023s%1023s%1023s", option_name, choice_name, printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             printf("%s\n", cpdbGetChoiceTranslation(p, option_name, choice_name, locale));
         }
@@ -446,7 +446,7 @@ gpointer parse_commands(gpointer user_data)
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
             char group_name[BUFSIZE];
-            scanf("%s%s%s", group_name, printer_id, backend_name);
+            scanf("%1023s%1023s%1023s", group_name, printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             printf("%s\n", cpdbGetGroupTranslation(p, group_name, locale));
         }
@@ -454,7 +454,7 @@ gpointer parse_commands(gpointer user_data)
         {
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
-            scanf("%s%s", printer_id, backend_name);
+            scanf("%1023s%1023s", printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             cpdbGetAllTranslations(p, locale);
             printTranslations(p);
@@ -465,7 +465,7 @@ gpointer parse_commands(gpointer user_data)
             char backend_name[BUFSIZE];
             char media[BUFSIZE];
             int width, length;
-            scanf("%s%s%s", media, printer_id, backend_name);
+            scanf("%1023s%1023s%1023s", media, printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             int ok = cpdbGetMediaSize(p, media, &width, &length);
             if (ok)
@@ -476,7 +476,7 @@ gpointer parse_commands(gpointer user_data)
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
             char media[BUFSIZE];
-            scanf("%s%s%s", media, printer_id, backend_name);
+            scanf("%1023s%1023s%1023s", media, printer_id, backend_name);
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
 
             cpdb_margin_t *margins;
@@ -488,7 +488,7 @@ gpointer parse_commands(gpointer user_data)
         {
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
-            scanf("%s%s", printer_id, backend_name);
+            scanf("%1023s%1023s", printer_id, backend_name);
             
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             if(p == NULL)
@@ -501,7 +501,7 @@ gpointer parse_commands(gpointer user_data)
         {
             char printer_id[BUFSIZE];
             char backend_name[BUFSIZE];
-            scanf("%s%s", printer_id, backend_name);
+            scanf("%1023s%1023s", printer_id, backend_name);
             
             cpdb_printer_obj_t *p = cpdbFindPrinterObj(f, printer_id, backend_name);
             if(p == NULL)

programming_language: C