It's not very clear from your question, but I suppose you're seeing the unexpected tags in the browser's DOM inspector. "Show Page Source" should show you the actual raw HTML your browser received.
Edit: what @AliN11 said
HTML infers tags when missing in content. In your case, the HTML browser knows that
h2 can't appear in the content of a
p element, hence it adds the
</p> end-element tag before
h2. Then after the
h2 element, it encounters the
</p> end-element tag, and inserts a
<p> start-element tag before it, because none is open at the context position.
The first insertion - that for the
</p> end-element tag - is part of the regular parsing rules for HTML; omitting
</p> is allowed according to the HTML specification. But the second insertion - that for the
<p> start-element tag - is not, and is an effect of HTML recovery (repair) kicking in.
I've explained HTML/SGML tag insertion in detail on the project page of my SGML software and the linked slides of a talk I gave about it last year.