diff --git a/ppd/ppd.c b/ppd/ppd.c index 35a5bf9d..181ebc59 100644 --- a/ppd/ppd.c +++ b/ppd/ppd.c @@ -844,6 +844,7 @@ ppdOpenWithLocalization( // Say all PPD files are UTF-8, since we convert to UTF-8... // + free(ppd->lang_encoding); ppd->lang_encoding = strdup("UTF-8"); encoding = ppdGetEncoding(string); } @@ -859,6 +860,7 @@ ppdOpenWithLocalization( ppd->pcfilename = string; else if (!strcmp(keyword, "NickName")) { + free(ppd->nickname); if (encoding != CUPS_ENCODING_UTF_8) { cups_utf8_t utf8[256]; // UTF-8 version of NickName @@ -878,22 +880,26 @@ ppdOpenWithLocalization( ppd->ttrasterizer = string; else if (!strcmp(keyword, "JCLBegin")) { + free(ppd->jcl_begin); ppd->jcl_begin = strdup(string); ppdDecode(ppd->jcl_begin); // Decode quoted string } else if (!strcmp(keyword, "JCLEnd")) { + free(ppd->jcl_end); ppd->jcl_end = strdup(string); ppdDecode(ppd->jcl_end); // Decode quoted string } else if (!strcmp(keyword, "JCLToPSInterpreter")) { + free(ppd->jcl_ps); ppd->jcl_ps = strdup(string); ppdDecode(ppd->jcl_ps); // Decode quoted string } #if HAVE_CUPS_3_X else if (!strcmp(keyword, "JCLToPDFInterpreter")) { + free(ppd->jcl_pdf); ppd->jcl_pdf = strdup(string); ppdDecode(ppd->jcl_pdf); // Decode quoted string } diff --git a/ppd/test_ppd_emit.c b/ppd/test_ppd_emit.c index cde32426..87e2dc3a 100644 --- a/ppd/test_ppd_emit.c +++ b/ppd/test_ppd_emit.c @@ -1013,6 +1013,47 @@ main(void) marked ? marked->choice : "(none)"); + // T47 — Duplicate *JCLBegin / *JCLEnd / *JCLToPSInterpreter / *NickName / + // *LanguageEncoding keywords in a PPD must not leak prior strdup() + // allocations (OpenPrinting/fuzzing#46). + testBegin("ppdOpen with duplicate JCLBegin/JCLEnd/JCLToPSInterpreter does not leak"); + { + static const char dup_jcl_ppd_text[] = + "*PPD-Adobe: \"4.3\"\n" + "*FormatVersion: \"4.3\"\n" + "*FileVersion: \"1.0\"\n" + "*LanguageVersion: English\n" + "*LanguageEncoding: ISOLatin1\n" + "*LanguageEncoding: ISOLatin1\n" + "*PCFileName: \"DUPJCL.PPD\"\n" + "*Manufacturer: \"Test\"\n" + "*Product: \"(Test Printer)\"\n" + "*ModelName: \"Test Duplicate JCL\"\n" + "*ShortNickName: \"TestDup\"\n" + "*NickName: \"First NickName\"\n" + "*NickName: \"Second NickName\"\n" + "*PSVersion: \"(3010.000) 0\"\n" + "*JCLBegin: \"first_begin<0A>\"\n" + "*JCLBegin: \"second_begin<0A>\"\n" + "*JCLToPSInterpreter: \"first_ps<0A>\"\n" + "*JCLToPSInterpreter: \"second_ps<0A>\"\n" + "*JCLEnd: \"first_end<0A>\"\n" + "*JCLEnd: \"second_end<0A>\"\n" + "*OpenUI *PageSize: PickOne\n" + "*DefaultPageSize: Letter\n" + "*PageSize Letter: \"\"\n" + "*CloseUI: *PageSize\n"; + ppd_file_t *ppd_dup = open_embedded_ppd(dup_jcl_ppd_text); + bool ok = ppd_dup != NULL && + ppd_dup->jcl_begin && !strcmp(ppd_dup->jcl_begin, "second_begin\n") && + ppd_dup->jcl_ps && !strcmp(ppd_dup->jcl_ps, "second_ps\n") && + ppd_dup->jcl_end && !strcmp(ppd_dup->jcl_end, "second_end\n") && + ppd_dup->nickname && !strcmp(ppd_dup->nickname, "Second NickName"); + testEnd(ok); + ppdClose(ppd_dup); + } + + // ------------------------------------------------------------------------- // Tear down and return success/failure based on the framework flag. // -------------------------------------------------------------------------