While investigating some odd behavior, I discovered that in FreeType if a TrueType glyf contains instructions which read/modify/write a CVT entry and the glyph is loaded more than once the modified values persist across calls. The persistence is in the (TT_SizeRec_) size.cvt since TT_Load_Context sets exec.cvt to size.cvt.
The size.cvt can be reset from the face.cvt in tt_size_run_prep which is called from tt_loader_init either directly or through tt_size_ready_bytecode. However this is only done if the cvt isn't ready or the rendering mode changed. If FT_Load_Glyph is called twice with the same FT_Face/FT_Size and the same flags the modified values will persist across the calls. This can lead to unexpected behavior where outlines hint differently depending on the order they are loaded.
I'm not sure if this is supposed to work this way. I don't think it should, but this doesn't seem to be addressed by any existing specification or documentation. It seems likeĀ TT_Load_Context should make a copy of size.cvt, or if a write is done to the cvt while hinting a glyph the size.cvt should be marked not ready so it will be recalculated, or some other copy/regenerate on write scheme.
I have one font in the wild which triggers this, Galasio-Bold. The fpgm defines a few subroutines which use WCVTP which get called by a few glyphs. The updates usually are stable, but with certain matrix which scale in y the updates no longer round to the same pixel value and start adding up. However, this can be abused for more interesting effects as well if used on purpose.
I haven't investigated other parts of size, but it is possible that the other pointers which are shared might also have this issue. For example function_defs, instruction_defs, storage, and twilight.