Skip to content

A stylesheet's image-url(...) is fetched and rewritten as if it were url() #1754

Description

@xroche

The CSS scanner reads any name ending in url before a ( as a url() link. Its guard refuses only an ASCII letter, a digit or _ in front of those three letters. The CSS ident set is wider than that, so a hyphenated function name is fetched and its argument rewritten.

Repro, a stylesheet with two controls and the cases. .c2 holds a raw U+1680 OGHAM SPACE MARK between x and url, and .c3 holds a raw U+FEFF ZERO WIDTH NO-BREAK SPACE. Both print as nothing below:

.c0{background:url(/img/a.png)}
.c1{background:image-url(/img/b.png)}
.c2{background:x url(/img/c.png)}
.c3{background:xurl(/img/d.png)}
.c5{background:myurl(/img/f.png)}

httrack fetched a.png, b.png, c.png and d.png, and never asked for f.png. The mirrored stylesheet comes back with four of the five values rewritten:

.c0{background:url(img/a.png)}
.c1{background:image-url(img/b.png)}
.c2{background:x url(img/c.png)}
.c3{background:xurl(img/d.png)}
.c5{background:myurl(/img/f.png)}

.c0 must be rewritten and is. .c5 must not be and is not, so the run can show a loss as well as a gain.

CSS Syntax 3 names - (U+002D) an ident code point, so image-url( is consumed as one function-token and never becomes a url-token. No browser resolves that argument. The mirror therefore fetches a file nobody asked for, and rewrites a declaration that a browser reads differently from us. Compass and the Rails asset pipeline both define image-url(), font-url() and asset-url(), so the spelling is common in stylesheet sources.

Every non-ASCII ident code point glues the same way, an accented letter included. U+1680 and U+FEFF are the invisible members of that set. They read as whitespace, and the spec's non-ASCII ident ranges still hold them.

Refusing - and every byte over 127 would also refuse the code points CSS treats as a delim, U+00A0 among them. There the url-token does form, so the argument really is a URL and only the declaration around it is invalid. Those are a separate question.

Two binaries show the same behaviour, 6b23ca8c from before #1743 and 6758bc36 from after it, so that PR neither caused nor fixed this. Found while reviewing it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions