Skip to content

HTML template in auth/oauth/u2m disables public dead code elimination for the whole application #343

@murfffi

Description

@murfffi

Use of the stdlib html/template in package auth/oauth/u2m disables public dead code elimination (DCE) for the whole application.
This significantly reduces the dead code elimination performed by the Go linker and increases the size of any binary that uses databricks-sql-go . The effect is especially significant in binaries where databricks-sql-go is one among many 3rd-party libraries like github.com/xo/usql, where full linker dead code elimination would reduce the binary by 20% (40 MB).

Several popular Go libraries already released similar fixes in the past two years: cobra, grpc, protobuf, and so on. Popular Go applications/services were able to release smaller binaries as a result: kubernetes, datadog-agent . Dead code elimination by the linker is not the be confused with source-level dead code detection like in https://go.dev/blog/deadcode . They are complementary.

Steps to reproduce:

  1. Put the code from the README.md example in a main.go. The code doesn't need to run, just needs to compile.
  2. Build it with the following command:
go build -ldflags=-dumpdep . |& go run github.com/aarzilli/whydeadcode@latest

Expected: no output, and the binary is built successfuly

Actual:

$ go build -ldflags=-dumpdep . |& go run github.com/aarzilli/whydeadcode@latest
text/template.(*state).evalField reachable from:
         text/template.(*state).evalFieldChain
         text/template.(*state).evalCommand
         text/template.(*state).evalPipeline
         text/template.(*state).walk
         text/template.(*Template).execute
         html/template.(*Template).Execute
         github.com/databricks/databricks-sql-go/auth/oauth/u2m.renderHTML
         github.com/databricks/databricks-sql-go/auth/oauth/u2m.(*tokenSourceProvider).ServeHTTP
         type:*github.com/databricks/databricks-sql-go/auth/oauth/u2m.tokenSourceProvider
         type:github.com/databricks/databricks-sql-go/auth/oauth/u2m.tokenSourceProvider
         github.com/databricks/databricks-sql-go/auth/oauth/u2m.GetTokenSourceProvider
         github.com/databricks/databricks-sql-go/auth/oauth/u2m.NewAuthenticator
         github.com/databricks/databricks-sql-go/internal/config.makeAuthenticator
         github.com/databricks/databricks-sql-go/internal/config.ParseDSN
         github.com/databricks/databricks-sql-go.(*databricksDriver).OpenConnector
         type:*github.com/databricks/databricks-sql-go.databricksDriver
         go:itab.*github.com/databricks/databricks-sql-go.databricksDriver,database/sql/driver.Driver
         github.com/databricks/databricks-sql-go.init.0
         github.com/databricks/databricks-sql-go..inittask
         go:main.inittasks
         _

Suggested solution: since the template at auth/oauth/u2m/templates/simple.html is not very dynamic, it can be rewritten as a series of string operations and explicit HTML escapting calls. This is how xo/tblfmt fixed a similar issue. In this case, the fix will be much simpler. I am happy to submit a PR if that makes sense.

There are a few alternative solutions which I don't recommend but are worth discussing:

  • there is a feature request for the Go stdlib to provide variants of text/template and html/template that don't disable DCE - proposal: text/template,html/template: Template.ExecuteLite skip resolution to methods to allow DCE golang/go#72895 . I don't recommend waiting for that because the proposal is still far away from acceptance. (Though it is not rejected either).
  • there is a fork of the stdlib template packages that doesn't disable DCE, essentially implementing that stdlib proposal. This is how Datadog enabled DCE in their agent. However, using that fork with a Go version different from the forked version may be problematic.
  • a build tag may be added that disables HTML rendering - this is how grpc fixed a similar issue - however, I believe the complexity isn't worth it in this case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions