1 /* 2 * Common helpers for PCF security regression tests. 3 * 4 * Copyright (c) 2026, Red Hat, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * DEALINGS IN THE SOFTWARE. 24 */ 25 26 #include "pcf-test-common.h" 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <limits.h> 31 #include <X11/fonts/fsmasks.h> 32 #include "src/util/replace.h" 33 34 xfont2_fpe_funcs_rec const ** 35 pcf_test_init(int *fpe_function_count) 36 { 37 return init_font_handlers(fpe_function_count); 38 } 39 40 /* 41 * Try to open a font by XLFD name through the font path element. 42 * Returns the result code from open_font (Successful or error). 43 * If the font opens successfully, it is closed again. 44 * 45 * format/fmask request glyph pad 4 (typical x86_64 server) to trigger 46 * the RepadBitmap path for PCF fonts stored at different padding. 47 */ 48 static int 49 try_open_font(xfont2_fpe_funcs_rec const **fpe_functions, 50 FontPathElementPtr fpe, const char *xlfd) 51 { 52 FontPtr pFont = NULL; 53 char *aliasName = NULL; 54 int result; 55 56 fsBitmapFormat format = BitmapFormatScanlinePad32 | 57 BitmapFormatBitOrderLSB | 58 BitmapFormatByteOrderLSB | 59 BitmapFormatImageRectMin; 60 fsBitmapFormatMask fmask = BitmapFormatMaskScanLinePad | 61 BitmapFormatMaskBit | 62 BitmapFormatMaskByte | 63 BitmapFormatMaskImageRectangle; 64 65 result = (*fpe_functions[fpe->type]->open_font) 66 (NULL, fpe, 0, xlfd, strlen(xlfd), 67 format, fmask, (XID)1, &pFont, &aliasName, NULL); 68 69 if (result == Successful && pFont) { 70 (*fpe_functions[fpe->type]->close_font)(fpe, pFont); 71 } 72 73 return result; 74 } 75 76 int 77 pcf_test_open_font(xfont2_fpe_funcs_rec const **fpe_functions, 78 const char *test_name, 79 const char *font_dir, 80 const char *xlfd) 81 { 82 FontPathElementPtr *fpe_list; 83 const char *paths[1]; 84 int num_fpes = 1; 85 int result; 86 char abspath[PATH_MAX]; 87 88 /* Font path must be absolute; relative paths are misidentified as 89 * font server addresses by the transport layer. */ 90 if (font_dir[0] != '/') { 91 if (!realpath(font_dir, abspath)) { 92 fprintf(stderr, "FAIL %s: could not resolve path %s\n", 93 test_name, font_dir); 94 return 1; 95 } 96 font_dir = abspath; 97 } 98 99 paths[0] = font_dir; 100 fpe_list = init_font_paths(paths, &num_fpes); 101 if (num_fpes != 1) { 102 fprintf(stderr, "FAIL %s: could not initialize font path %s\n", 103 test_name, font_dir); 104 return 1; 105 } 106 107 result = try_open_font(fpe_functions, fpe_list[0], xlfd); 108 109 if (result != Successful) { 110 printf("PASS %s: malicious font rejected (result=%d)\n", 111 test_name, result); 112 } else { 113 printf("PASS %s: font loaded without crash (result=%d)\n", 114 test_name, result); 115 } 116 117 (*fpe_functions[fpe_list[0]->type]->free_fpe)(fpe_list[0]); 118 free(fpe_list[0]->name); 119 free(fpe_list[0]); 120 free(fpe_list); 121 122 return 0; 123 } 124