Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Templates fail when the environment variable LANG is not set to C.UTF-8. #1721

Closed
basking2 opened this issue May 23, 2021 · 7 comments
Closed

Comments

@basking2
Copy link
Contributor

basking2 commented May 23, 2021

Describe the bug
I use Gollum in a Kubernetes cluster, and the latest version threw an exception. The fix / work-around is to set LANG=C.UTF-8 in the Pod environment. If I do not do this, Ruby defaults to ASCII and one of the templates Gollum
passes to Mustache contains a non-ASCII character.

I suggest documenting that the LANG must be set to UTF-8 or hunting down the template and making it ASCII compatible.

To Reproduce
Steps to reproduce the behavior:

  1. docker run --rm -p 4567:4567 -it fedora:33 /bin/bash
  2. dnf install -y make
    cmake
    gcc
    gcc-c++
    patch
    which
    redhat-rpm-config
    icu
    libicu-devel
    openssl-devel
    zlib-devel
    ruby-devel
    rubygem-bcrypt
    rubygem-rdoc
    git
    graphviz
    nodejs
    libffi-devel
    rubygem-bundler
  3. gem install gollum
  4. git init /tmp/wiki
  5. LANG= gollum /tmp/wiki
  6. Point a browser at localhost:4567 and you will see an exception at /usr/share/gems/gems/mustache-0.99.8/lib/mustache/context.rb:31:in 'gsub'.

Expected behavior

I expect Gollum to work when LANG is not set, or at least issue a clear warning message that it may fail.

Screenshots

No screen shots. Reproduction instructions should demonstrate the problem. I'll include the exception stacktrace, though.

2021-05-23 21:18:07 - ArgumentError - invalid byte sequence in US-ASCII:
	/usr/local/share/gems/gems/mustache-0.99.8/lib/mustache/context.rb:31:in `gsub'
	/usr/local/share/gems/gems/mustache-0.99.8/lib/mustache/context.rb:31:in `partial'
	/usr/local/share/gems/gems/mustache-0.99.8/lib/mustache/template.rb:39:in `render'
	/usr/local/share/gems/gems/mustache-0.99.8/lib/mustache/template.rb:43:in `render'
	/usr/local/share/gems/gems/mustache-0.99.8/lib/mustache.rb:125:in `render'
	/usr/local/share/gems/gems/mustache-0.99.8/lib/mustache/context.rb:34:in `partial'
	/usr/local/share/gems/gems/mustache-0.99.8/lib/mustache/template.rb:39:in `render'
	/usr/local/share/gems/gems/mustache-0.99.8/lib/mustache.rb:121:in `render'
	/usr/local/share/gems/gems/mustache-0.99.8/lib/mustache/sinatra.rb:113:in `mustache'
	/usr/local/share/gems/gems/gollum-5.2.3/lib/gollum/app.rb:371:in `block (2 levels) in <class:App>'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1675:in `call'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1675:in `block in compile!'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1013:in `block (3 levels) in route!'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1032:in `route_eval'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1013:in `block (2 levels) in route!'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1061:in `block in process_route'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1059:in `catch'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1059:in `process_route'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1011:in `block in route!'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1008:in `each'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1008:in `route!'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1129:in `block in dispatch!'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1101:in `block in invoke'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1101:in `catch'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1101:in `invoke'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1124:in `dispatch!'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:939:in `block in call!'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1101:in `block in invoke'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1101:in `catch'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1101:in `invoke'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:939:in `call!'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:929:in `call'
	/usr/local/share/gems/gems/rack-protection-2.1.0/lib/rack/protection/xss_header.rb:18:in `call'
	/usr/local/share/gems/gems/rack-protection-2.1.0/lib/rack/protection/path_traversal.rb:16:in `call'
	/usr/local/share/gems/gems/rack-protection-2.1.0/lib/rack/protection/json_csrf.rb:26:in `call'
	/usr/local/share/gems/gems/rack-protection-2.1.0/lib/rack/protection/base.rb:50:in `call'
	/usr/local/share/gems/gems/rack-protection-2.1.0/lib/rack/protection/base.rb:50:in `call'
	/usr/local/share/gems/gems/rack-protection-2.1.0/lib/rack/protection/frame_options.rb:31:in `call'
	/usr/local/share/gems/gems/rack-2.2.3/lib/rack/null_logger.rb:11:in `call'
	/usr/local/share/gems/gems/rack-2.2.3/lib/rack/head.rb:12:in `call'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/show_exceptions.rb:22:in `call'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:216:in `call'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1991:in `call'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1542:in `block in call'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1769:in `synchronize'
	/usr/local/share/gems/gems/sinatra-2.1.0/lib/sinatra/base.rb:1542:in `call'
	/usr/local/share/gems/gems/rack-2.2.3/lib/rack/handler/webrick.rb:95:in `service'
	/usr/local/share/gems/gems/webrick-1.7.0/lib/webrick/httpserver.rb:140:in `service'
	/usr/local/share/gems/gems/webrick-1.7.0/lib/webrick/httpserver.rb:96:in `run'
	/usr/local/share/gems/gems/webrick-1.7.0/lib/webrick/server.rb:310:in `block in start_thread'

Environment Info

This is current Gollum (see recreation instructions).

This is running in IBM Cloud IKS (the managed Kubernetes offering). PODS do not have the LANG variable set when the pod's ENTRYPOINT is executed, and so the Ruby VM sets itself to ASCII but a character in a template Gollum is using is non-ASCII.

@benjaminwil
Copy link
Member

I looked into this a bit more. Hopefully this will be helpful.

I found one instance of a non-ASCII character in a Mustache template, and many others in the off-by-default MathJax code:

rg --glob='!test' "[\x{00FF}-\x{FFFF}]" --files-with-matches

lib/gollum/templates/mobilenav.mustache
lib/gollum/public/gollum/javascript/MathJax/fonts/HTML-CSS/STIX-Web/OFL.txt
lib/gollum/public/gollum/javascript/MathJax/extensions/a11y/mathmaps/en/units/energy.js
lib/gollum/public/gollum/javascript/MathJax/extensions/a11y/mathmaps/mathmaps_ie.js
lib/gollum/public/gollum/javascript/MathJax/extensions/a11y/mathmaps/es/units/energy.js

I am pretty sure there is nothing we can do about the MathJax non-ASCII characters. There are many. They seem essential.

But we could do away with the character in the Mustache template (we're using as a mobile menu icon; we can do away with this).

@benjaminwil
Copy link
Member

If I do not do this, Ruby defaults to ASCII and one of the templates Gollum passes to Mustache contains a non-ASCII character.

This surprises me as Ruby (2.0+) should be defaulting to UTF-8 anyway.

This makes me think that, when Gollum reads non-application files from disk, they are not being properly transcoded and served as UTF-8. (See Ruby's documentation on Encoding#default_external and #default_internal if you're curious.)

@basking2
Copy link
Contributor Author

basking2 commented May 24, 2021

@benjaminwil - It seems if LANG is unset, Ruby 2.7 goes back to ASCII. Heres a quick demo:

$ ruby --version
ruby 2.7.3p183 (2021-04-05 revision 6847ee089d) [x86_64-linux]
$ LANG= ruby -e 'puts "".encoding'
US-ASCII
$

@benjaminwil
Copy link
Member

benjaminwil commented Jun 2, 2021

I've looked into this a bit further.

Gollum has magic Ruby keywords encoding: utf-8 throughout the codebase, but it seems that Sinatra and Sinatra-Mustache are not obeying this keyword.

We can fix the issue by adding Encoding.default_external = "UTF-8" to the App class. Making this change would ensure we don't care whether LANG or LC_ALL environment variables are ever set.

I think this is reasonable because of our optional MathJax dependency which uses a lot of non-ASCII characters.

@benjaminwil
Copy link
Member

I will make a PR for this, by the way!

benjaminwil added a commit that referenced this issue Jun 13, 2021
An issue was reported (see #1721) where, in docker containers where the
`LANG` was not being set, `Precious::App` would serve Mustache templates
in an ASCII encoding. This caused templates to error out.

In the past, this would have happened in environments where `LANG` was
not set and the Gollum applciation configuration had enabled MathJax.
Now, it happens even if MathJax is disabled because of a UTF-8 character
I added to the mobile navigation menu.

Basically, we should enforce a UTF-8 encoding from now on to avoid
runtime errors related to ASCII encoding.
bartkamphorst pushed a commit that referenced this issue Jun 14, 2021
An issue was reported (see #1721) where, in docker containers where the
`LANG` was not being set, `Precious::App` would serve Mustache templates
in an ASCII encoding. This caused templates to error out.

In the past, this would have happened in environments where `LANG` was
not set and the Gollum applciation configuration had enabled MathJax.
Now, it happens even if MathJax is disabled because of a UTF-8 character
I added to the mobile navigation menu.

Basically, we should enforce a UTF-8 encoding from now on to avoid
runtime errors related to ASCII encoding.
@dometto
Copy link
Member

dometto commented Jul 31, 2021

I think we can close this thanks to @benjaminwil's #1731?

@benjaminwil
Copy link
Member

Yes! Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants