1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-24 22:01:47 +03:00

wezterm: fix infinite recursion when no valid fallbacks are present

This config reproduces the issue:

```lua
local wezterm = require "wezterm"

return {
  font_size = 12.0,
  font_dirs = {"fonts"}, -- relative to this config file
  font_locator = "ConfigDirsOnly",
  font = wezterm.font_with_fallback({
    -- this is an invalid font
    "does not exist",
    -- this is a valid font, with only symbols
    "Font Awesome 5 Free Solid",
  }),
}
```

the existing protections were a bit simplistic, so now we have a
dedicated error type for this case and that stops fallback processing
from recursing.

closes: https://github.com/wez/wezterm/issues/279
This commit is contained in:
Wez Furlong 2020-09-27 09:02:43 -07:00
parent 0e8ac1851d
commit 9d33073d70

View File

@ -4,9 +4,10 @@ use crate::font::hbwrap as harfbuzz;
use crate::font::locator::FontDataHandle; use crate::font::locator::FontDataHandle;
use crate::font::shaper::{FallbackIdx, FontMetrics, FontShaper, GlyphInfo}; use crate::font::shaper::{FallbackIdx, FontMetrics, FontShaper, GlyphInfo};
use crate::font::units::*; use crate::font::units::*;
use anyhow::{anyhow, bail}; use anyhow::anyhow;
use log::{debug, error}; use log::{debug, error};
use std::cell::{RefCell, RefMut}; use std::cell::{RefCell, RefMut};
use thiserror::Error;
fn make_glyphinfo( fn make_glyphinfo(
text: &str, text: &str,
@ -43,6 +44,12 @@ pub struct HarfbuzzShaper {
lib: ftwrap::Library, lib: ftwrap::Library,
} }
#[derive(Error, Debug)]
#[error("No more fallbacks while shaping {}", .text.escape_unicode())]
struct NoMoreFallbacksError {
text: String,
}
impl HarfbuzzShaper { impl HarfbuzzShaper {
pub fn new(handles: &[FontDataHandle]) -> anyhow::Result<Self> { pub fn new(handles: &[FontDataHandle]) -> anyhow::Result<Self> {
let lib = ftwrap::Library::new()?; let lib = ftwrap::Library::new()?;
@ -119,8 +126,10 @@ impl HarfbuzzShaper {
pair.font.shape(&mut buf, Some(features.as_slice())); pair.font.shape(&mut buf, Some(features.as_slice()));
} }
None => { None => {
let chars: Vec<u32> = s.chars().map(|c| c as u32).collect(); return Err(NoMoreFallbacksError {
bail!("No more fallbacks while shaping {:x?}", chars); text: s.to_string(),
}
.into());
} }
} }
} }
@ -188,8 +197,8 @@ impl HarfbuzzShaper {
Ok(shape) => Ok(shape), Ok(shape) => Ok(shape),
Err(e) => { Err(e) => {
error!("{:?} for {:?}", e, substr); error!("{:?} for {:?}", e, substr);
if font_idx == 0 && s == "?" { if e.downcast_ref::<NoMoreFallbacksError>().is_some() {
bail!("unable to find any usable glyphs for `?` in font_idx 0"); return Err(e);
} }
self.do_shape(0, "?", font_size, dpi) self.do_shape(0, "?", font_size, dpi)
} }
@ -230,8 +239,8 @@ impl HarfbuzzShaper {
Ok(shape) => Ok(shape), Ok(shape) => Ok(shape),
Err(e) => { Err(e) => {
error!("{:?} for {:?}", e, substr); error!("{:?} for {:?}", e, substr);
if font_idx == 0 && s == "?" { if e.downcast_ref::<NoMoreFallbacksError>().is_some() {
bail!("unable to find any usable glyphs for `?` in font_idx 0"); return Err(e);
} }
self.do_shape(0, "?", font_size, dpi) self.do_shape(0, "?", font_size, dpi)
} }