Home | History | Annotate | Line # | Download | only in test
      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