The South Africans were one stroke from victory at 206 for six, chasing Sri Lanka's modest 209, before Malinga struck. He became the first bowler to take wickets with four consecutive balls in a limited-overs international.
Australia defeated West Indies by 103 runs in a match completed yesterday after rain delays Tuesday.
Sri Lanka's Malinga removed Shaun Pollock (13) and Andrew Hall (0) on the last two balls of his eighth over -- the 45th -- and Jacques Kallis (86) caught behind and Makhaya Ntini bowled on the first two balls of his ninth.
That left South Africa needing three runs from 21 balls.
Robin Peterson edged Malinga for four down to third man to take South Africa to 212-9 with 10 balls to spare. Peterson jumped jubilantly as he ran down the pitch in celebration and then smashed the stumps at the non-striker's end with his bat.
Malinga returned 4-54 from 9.2 overs and Muttiah Muralitharan, who had a loud shout for a hat trick, turned down earlier in the innings, finished with 3-34.
The win ensured South Africa of top spot in the season-ending international limited-overs rankings come April 1, regardless of whatever else happens in the World Cup.
Despite the close shave, the win was a confidence boost for the South Africans, and a slight come down for Sri Lanka after its 3-0 sweep in Group B included wins over India and Bangladesh.
Charl Langeveldt did the early damage with a career-best 5-39 to restrict the Sri Lankans to their lowest total of the Cup after Mahela Jayawardene had won the toss and elected to bat. Langeveldt took three wickets in his last over as Sri Lanka lost its last four wickets for one run in seven balls. He'll start South Africa's next match on a hat trick.
Coming in when AB de Villiers was bowled by Chaminda Vaas in the first over, Kallis scored 86 and shared a 94-run stand with Graeme Smith (59) that set up South Africa's chase.
His 110-ball innings contained four boundaries.
Muralitharan caused a wobble in the middle when he dismissed Herschelle Gibbs (31) and Mark Boucher on consecutive balls to make it 160-4. The Sri Lankan spinner missed a hat trick when his next ball just missed the edge and bounced off Justin Kemp's pad into the hands of a close-in fielder. Kemp scored five before he was stumped off Jayasuriya's bowling with the total at 182, giving Kumar Sangakkara his second stumping -- he combined with Muralitharan to remove Smith in the 18th over.
Kallis anchored the innings, scoring 70 runs between two reprieves: a tough chance at first slip put down by Jayawardene on six and another sharp return catch put down by Malinga.
Smith scored his fourth consecutive half-century, facing 65 balls and hitting seven boundaries and a six to continue a run of good form.
Tillekaratne Dilshan (58) and Russel Arnold (50) shared a 97-run sixth-wicket to bolster the Sri Lanka innings after Ntini and Langeveldt had them struggling at 98-5. Ntini had Upul Tharanga (12) caught at slip with the total at 13.
Sanath Jayasuriya took a liking to Pollock's bowling, however, hitting 26 from 27 balls before he was undone by a change in the attack.
South Africa plays Ireland next Tuesday, three days after Sri Lanka plays host West Indies in Guyana.