Mattia Destro scored the winner in the seventh minute of extra-time while Fiorentina hit the woodwork three times in a match marred by a brawl centred around Fiorentina's Juan Cuadrado and Roma's Dodo.
The Colombian and the Brazilian pushed each other several times after tussling for the ball, prompting other players to try to intervene.
Both were given straight red cards but they continued to argue as they left the pitch, leading to another scramble which also involved several stewards, one falling over backwards, before their team mates intervened to calm the situation.
Roma also had Brazilian midfielder Rodrigo Taddei sent off in the 117th minute after he picked up two yellow cards in three minutes, the second for obstruction on Borja Valero off the ball.
Fiorentina were first denied when Alberto Aquilani hit the crossbar with Roma goalkeeper Marco Goicochea beaten just before halftime.
Daniele De Rossi had a goal disallowed for offside before both teams came close to scoring at the end of normal time.
Valero cracked a shot against the post, then Roma went up the other end and Destro's goalbound chip was cleared off the line by Stefan Savic.
Roma, who face Inter Milan in the semi-finals, broke through when Miralem Pjanic got to the byline and his cross was turned in by Destro from close range.
Cuadrado volleyed against the foot of the post as Fiorentina were denied for a third time before the match degenerated.