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