The Fireball classes (including "Fireball", "SmallFireball", "DragonFireball", and "WitherSkull") are meant to kill themselves if they're inside the ground after 600 ticks. However, this does not happen automatically because the necessary requirements cannot be achieved without the aid of commands or third-party editors.
Info:
1. The "xTile", "yTile", and "zTile" values are meant to store its current location but do not, all defaulting to either -1 if created normally (ghast firing) or 0 if using the /summon command (and not specifying them manually). Those values are never updated automatically, staying at what they default to/are manually defined as.
2. The "inTile" tag is supposed to store the current block the fireball is within, defaulting to "minecraft:air". However, it also never updates, requiring the use of commands to change its value.
3. The "inGround" tag is supposed to state whether or not the fireball is inside the ground. This also never gets updated even if the fireball is in the ground, so requires the use of commands to set it to 1.
4. The "life" tag, new to 1.9, stores how long the fireball has been underground. Once this value reaches 600 after requirements are met, then the fireball is deleted.
Requirements:
1. "inGround" must be 1 (only achievable through commands).
2. "xTile", "yTile", and "zTile" must point to a block that has the same ID as the one defined in "inTile" (only changed by commands).
3. "life" must be 600 (works correctly, but only if the above functions).
4. Once all of the above are met, the fireball is killed.
Example (working, with aid):
Ensure that at (0,0,0) in your world, there is bedrock. Summon the following fireball, defaulting "xTile", "yTile", and "zTile" to 0:
/summon minecraft:fireball 0.0 15.0 0.0 {direction:[0.0,0.0,0.0],inGround:1b,inTile:"minecraft:bedrock",life:540}
After 3 seconds, the fireball will be deleted. Note that the xTile/yTile/zTile are pointing to (0,0,0) and yet the Fireball itself is at (0,15,0), showing that the tags do not update. Since there was bedrock where the tile tags were pointing to, and because the "inGround" tag is set to 1, the fireball is able to be deleted.
Example (not working, no aid):
Ensure that at (5,0,5) in your world, there is any non-air block, preferably bedrock for testing consistency. Summon the following fireball:
/summon minecraft:fireball 5.0 0.0 5.0 {direction:[0.0,0.0,0.0],life:540}
It will be summoned into the ground at the position of the bedrock. "inGround" will never become 1, "xTile", "yTile", and "zTile" will never change from (0,0,0), "inTile" will always be "minecraft:air", and "life" will remain at the defined 540.
Example 2 (not working, no aid, no /summon):
Summon a Ghast:
/summon minecraft:ghast ~ ~1 ~
Go into survival mode, allow it to shoot a fireball at you, and then run the following command while the fireball still exists (or use a third-party NBT editor):
/entitydata @e[type=minecraft:fireball,c=1] {}
You will obtain the data of the entity, in that "xTile", "yTile", and "zTile" are always -1.
Conclusion:
The fix, as implied already, is to correctly track xTile/yTile/zTile, inGround, and inTile. Projectile classes (arrows) do this same thing correctly, although they are tracking a maximum of 1200 ticks instead of 600. Note that fireball classes are not extending projectile classes; they are completely separate. The addition of the "life" tag in 1.9 for fireballs implies that this is an intentional feature (this problem occurs in 1.8 as well), but is not capable of running without the aid described above.
Related issues
Comments


The only thing I can imagine it being used for is when a fireball is shot into lava and slows to a halt. Without the code working, it wouldn't be deleted since it won't crash into a block.

Projectiles are glitchy. You can fix this by doing so. Repeating Command Block set to "Always Active".
/execute @e[type=Fireball] ~ ~ ~ detect ~ ~ ~ minecraft:air 0 testfor @e[type=Fireball,c=1,r=0] {direction:[0.0,0.0,0.0]}
Conditional Chain Command Block set to "Always Active" with following command below.
/execute @e[type=Fireball] ~ ~ ~ detect ~ ~ ~ minecraft:air 0 entitydata @e[type=Fireball,c=1,r=0] {inGround:1,xTile:0,yTile:1,zTile:0,inTile:"minecraft:bedrock",life:580}
If that didn't work, ignore above.

@No Name1, This will not work due to redundancy in checking the "direction" tag. If any of the 3 values in the fireball's "direction" tag is 0, the /testfor is successful (as "direction:[0.0,0.0,0.0]" is the exact same as "direction:[0.0]" as far as accessing pre-existing lsit data goes). See my comments here for details. While there's a work-around for detecting immobile players via auto-incrementing objectives, those objectives do not affect non-player entities. Non-player entities are harder to accurately detect as being immobile, requiring methods such as teleporting anchor entities and checking distance between the two.

@Skylinerw Ok, then try the "Anchor Entities" method, as you described above.

The relevant tags and code have been deleted as of 16w40a.
Relates to:
MC-81659
Confirmed for
15w35b
To be honest I don't quite understand why these conditions must be true for the Fireball to be removed. This sounds rather like it is copied from the Arrow. Because normal Fireballs explode when hitting a block.