View Issue Details

IDProjectCategoryView StatusLast Update
0017393MediaMonkey 4Framework: Scripts/Extensionspublic2021-01-18 15:57
Reporterzvezdan Assigned To 
PriorityurgentSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Product Version4.1 
Target Version4.1.31Fixed in Version5.0.0 
Summary0017393: MM's UpperW DB function has massive memory leak causing catastrophic failure
DescriptionWhen used in more complex queries, the UpperW function has a massive memory leak causing the catastrophic failure. For years, I though that complex queries created by Magic Nodes are the reason for the program crashes, as it is recently reported to me:
https://www.mediamonkey.com/forum/viewtopic.php?p=476751#p476751

However, the real reason for that is using of the UpperW function. When I replaced it with Upper, there is no memory leaks nor program crashes.

Here is the test script which crashes the program after 48 loops on computer with 32-bit Vista and 3 GB RAM:
Option Explicit

Dim lblTest

Sub OnStartUp()
    Dim oMenuItem

    Set oMenuItem = SDB.UI.AddMenuItem(SDB.UI.Menu_File, 0, 0)
    With oMenuItem
        .Caption = "Test UpperW"
        .OnClickFunc = "Test"
        .UseScript = Script.ScriptPath
    End With
End Sub

Sub Test(oMenuItem)
    Dim oForm
    Dim oCtrl

    Set oForm = SDB.UI.NewForm
    With oForm
        .Common.SetRect 100, 100, 350, 140
        .BorderStyle = 3
        .FormPosition = 4
        .Caption = oMenuItem.Caption
    End With

    Set lblTest = SDB.UI.NewLabel(oForm)
    With lblTest
        .Common.SetRect 10, 10, 300, 17
        .Caption = "..."
    End With

    Set oCtrl = SDB.UI.NewButton(oForm)
    With oCtrl
        .Caption = "UpperW"
        .Common.SetRect 20, 70, 90, 25
    End With
    Script.RegisterEvent oCtrl, "OnClick", "UpperW"

    Set oCtrl = SDB.UI.NewButton(oForm)
    With oCtrl
        .Caption = "Upper"
        .Common.SetRect 120, 70, 90, 25
    End With
    Script.RegisterEvent oCtrl, "OnClick", "Upper"

    Set oCtrl = SDB.UI.NewButton(oForm)
    With oCtrl
        .Caption = SDB.Localize("&Close")
        .Common.SetRect 220, 70, 90, 25
        .Cancel = True
        .ModalResult = 2
    End With

    oForm.showModal
End Sub

Sub Upper()
    Dim oDbIter
    Dim sQuery
    Dim i

    sQuery = "SELECT SubStr(SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), InStr(Upper(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1), 1, InStr(Upper(SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), InStr(Upper(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') - 1) COLLATE IUNICODE AS MainField, Count(DISTINCT NullIf(SubStr(SubStr(SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), InStr(Upper(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1), InStr(Upper(SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), InStr(Upper(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1), 1, InStr(Upper(SubStr(SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), InStr(Upper(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1), InStr(Upper(SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), InStr(Upper(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') - 1) COLLATE IUNICODE, '')) AS StatField1 FROM Songs INNER JOIN (SELECT *, CASE WHEN DriveLetter IS NOT NULL THEN SubStr('ABCDEFGHIJKLMNOPQRSTUVWXYZ', DriveLetter + 1, 1) ELSE '' END AS DriveStr FROM Medias) AS Medias2 ON Songs.IDMedia = Medias2.IDMedia WHERE MainField <> '' AND SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), 1, InStr(Upper(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') - 1) COLLATE IUNICODE = 'So' AND SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), 1, InStr(Upper(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') - 1) COLLATE IUNICODE = 'Copy of Music' AND SubStr(Medias2.DriveStr || Songs.SongPath, 1, InStr(Upper(Medias2.DriveStr || Songs.SongPath) || '\', '\') - 1) COLLATE IUNICODE = 'C:' GROUP BY MainField ORDER BY MainField"
    For i = 1 To 100
        Set oDbIter = SDB.Database.OpenSQL(sQuery)
        lblTest.Caption = i
        SDB.ProcessMessages
        Set oDbIter = Nothing
    Next
End Sub

Sub UpperW()
    Dim oDbIter
    Dim sQuery
    Dim i

    sQuery = "SELECT SubStr(SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), InStr(UpperW(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1), 1, InStr(UpperW(SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), InStr(UpperW(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') - 1) COLLATE IUNICODE AS MainField, Count(DISTINCT NullIf(SubStr(SubStr(SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), InStr(UpperW(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1), InStr(UpperW(SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), InStr(UpperW(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1), 1, InStr(UpperW(SubStr(SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), InStr(UpperW(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1), InStr(UpperW(SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), InStr(UpperW(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') - 1) COLLATE IUNICODE, '')) AS StatField1 FROM Songs INNER JOIN (SELECT *, CASE WHEN DriveLetter IS NOT NULL THEN SubStr('ABCDEFGHIJKLMNOPQRSTUVWXYZ', DriveLetter + 1, 1) ELSE '' END AS DriveStr FROM Medias) AS Medias2 ON Songs.IDMedia = Medias2.IDMedia WHERE MainField <> '' AND SubStr(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1), 1, InStr(UpperW(SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') + 1)) || '\', '\') - 1) COLLATE IUNICODE = 'So' AND SubStr(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1), 1, InStr(UpperW(SubStr(Medias2.DriveStr || Songs.SongPath, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') + 1)) || '\', '\') - 1) COLLATE IUNICODE = 'Copy of Music' AND SubStr(Medias2.DriveStr || Songs.SongPath, 1, InStr(UpperW(Medias2.DriveStr || Songs.SongPath) || '\', '\') - 1) COLLATE IUNICODE = 'C:' GROUP BY MainField ORDER BY MainField"
    For i = 1 To 100
        Set oDbIter = SDB.Database.OpenSQL(sQuery)
        lblTest.Caption = i
        SDB.ProcessMessages
        Set oDbIter = Nothing
    Next
End Sub
Additional InformationYes, I know, this is about MM4 that you don't support anymore, but I bet you are using the same UpperW function in MM5 database as well.
TagsNo tags attached.
Fixed in build

Activities

There are no notes attached to this issue.