Menu

#373 WrongEncodingException handling is broken in loadTemplate.

2.3.21
closed-fixed
nobody
5
2014-10-12
2012-10-08
No

In the freemarker.cache.TemplateCache object

the loadTemplate method is broken:

The following code fragment:

try {
template = new Template(name, reader, config, encoding);
}
catch (Template.WrongEncodingException wee) {
encoding = wee.specifiedEncoding;
reader = loader.getReader(source, encoding);
template = new Template(name, reader, config, encoding);
}
template.setLocale(locale);

tries to load the template, then if it fails with a WrongEncodingException, it tries to load again with a different encoding.

The problem is that the second attempt uses the same URLTemplateSource instance as the first attempt, and that URLTemplateSource instance caches the open URLConnection instance that points to the template file. As a result, the first Template constructor reads the first chunk of the file, throws a WrongEncodingException, then the second Template constructor tries to read the template file, but the position in the file is not reset, so it fails to parse.

The bug is hard to trigger, I encountered it while loading a template from the classpath, on a resin-4.0.18 app server, and specified "utf.-8" instead of "UTF-8" as XML as well as FTL encoding.

Discussion

  • Tóth István

    Tóth István - 2012-10-08

    type, I mean "utf-8" instead of "UTF-8"

     
  • Dániel Dékány

    Ugh... that's a nice one. From the Version History:

    Bug fixed [373]: These are three bugs actually, which can cause problems when FreeMarker re-loads a template because of a charset override with <#ftl encoding="...">: First, if the template loader was a URLTemplateLoader, when TemplateLoader.getReader() was called for the second time, and the Reader returned for the first time was already used, it might returned an empty or corrupted template, depending on the backing URL implementation. Secondly, when FreeMarer has decided if a template file has to be re-loaded because its encoding specified with <#ftl encoding="..."> differs from the encoding used for loading the template first, it has used case-sensitive comparison, thus often re-loaded needlessly (like "UTF-8" and "utf-8" mean the same). Now this comparison is case-insensitive. Last not least, when retrying with the second charset, the TemplateCache has forgotten to close the first Reader, which can be a handle leak.

     

    Last edit: Dániel Dékány 2014-06-15
  • Dániel Dékány

    • status: open --> open-fixed
    • Group: --> 2.3.21
     
  • Dániel Dékány

    • status: open-fixed --> closed-fixed
     

Log in to post a comment.