Register recovery error(is this a bug or faults of my code?)

Everything else that doesn't fall into one of the other PB categories.
sonic3d
New User
New User
Posts: 9
Joined: Thu Oct 02, 2003 2:36 pm

Register recovery error(is this a bug or faults of my code?)

Post by sonic3d »

I recently wrote these code,and suffered written to readonly memory error.
I debuged the code in IDA,and found after all the code of this function executed,the return address in stack is pointed error by ESP(four bytes lower than the exact address which stored the correct return address)

Some one help me?

*Note1:The messagebox call--MessageRequester("Hello","HelloText") is added for easy deassembly,you can rip it out.
*Note2:The purpose of these code is to process a line in the specific CSV format file.

Code: Select all

Procedure.s GetCsvItemString(*FullString.s)
  MessageRequester("Hello","HelloText")
  StartPos.l=0
  EndPos.l=0
  RtString.s = ""
  If (Chr(34)=Left(*FullString.s,1))
    StartPos.l=2
    EndPos.l = FindString(*FullString.s,Chr(34)+",",2)
    RtString.s = Mid(*FullString.s,StartPos.l,EndPos-StartPos)
    *FullString.s = Mid(*FullString.s,EndPos+2,Len(*FullString.s)-EndPos+1-2)
  Else
    StartPos.l=1
    EndPos.l = FindString(*FullString.s,",",1)
    RtString.s = Mid(*FullString.s,StartPos.l,EndPos-StartPos)
    *FullString.s = Mid(*FullString.s,EndPos+1,Len(*FullString.s)-EndPos+1-1)
  EndIf
  MessageRequester("Hello","HelloText")
  ProcedureReturn RtString
EndProcedure

Title.s = GetCsvItemString(CurrLineText$)
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post by fweil »

sonic3d,

Maybe yur idea was like that ?

Code: Select all

Procedure.s GetCsvItemString(FullString.s)
  StartPos.l = 0
  EndPos.l = 0
  RtString.s = ""
  If Left(FullString.s, 1) = Chr(34)
    StartPos.l = 2
    EndPos.l = FindString(FullString.s, Chr(34) + ",", 2)
    RtString.s = Mid(FullString.s, StartPos.l, EndPos - StartPos)
    FullString.s = Mid(FullString.s, EndPos + 2, Len(FullString.s) - EndPos + 1 - 2)
  Else
    StartPos.l = 1
    EndPos.l = FindString(FullString.s, ",", 1)
    RtString.s = Mid(FullString.s, StartPos.l, EndPos - StartPos)
    FullString.s = Mid(FullString.s, EndPos + 1,Len(FullString.s) - EndPos + 1 - 1)
  EndIf
  ProcedureReturn RtString
EndProcedure

CurrLineText$ = "Title, sub title"
MessageRequester("Hello", GetCsvItemString(CurrLineText$), #PB_MessageRequester_Ok)
CurrLineText$ = Chr(34) + "Title" + Chr(34) + ", " + Chr(34) + "sub title" + Chr(34)
MessageRequester("Hello", GetCsvItemString(CurrLineText$), #PB_MessageRequester_Ok)
Let me know if I was wrong ...
My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
sonic3d
New User
New User
Posts: 9
Joined: Thu Oct 02, 2003 2:36 pm

Post by sonic3d »

Thanks,fweil! :lol:

But my purpose is to process a line in CSV file like this(Shoud be in one line):

Code: Select all

1,"SAS/ETS 9.1 User's Guide. Volume 1",,"SAS Publishing",2004,108350,0,SAS/ETS.,005.36,"HA30.3.S274 2004eb",Available,$231.95,,1590472446',1590474120',
some items in this string contain quote which should be stripped,and other values contain no quote can be directly stored.Finally, return the stored string.
***Why I use string point value as parameter of this function is for an easy changing to the *FullString.s I passed in.After the function finished get the first item from *FullString.s, the first item and the followed comma will be removed so that the *FullString.s could be pass to the function again to get next item easily without additional change outside this function.

Thus,point value is must to be used I thought.

But how can I deal this retvalue/stack prob?
I can change the machine code after compiled,but it's not a good way I thought.

Somebody help me! :shock:
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post by fweil »

sonic3d,

Well, I guess I understand well what you need.

The problem is to parse fields, usually coma separated, by getting them one after the other from a procedure that will process the good stuf to separate them.

The best way I suppose is to use StringField() command. Then from each field you can change anything you want in fields or transpose characters to values etc.

My way to code such behaviour would be something like the following sample code. I made a more generic string parser with separator and delimiter args for possible extended use.

Here the procedure improves the StringField() function.

Code: Select all

Procedure.s EnumCSVFields(String.s, Status.l, Separator.s, Delimiter.s)
  Static FieldID
    If Status = #FALSE
        FieldID = -1
    EndIf
    FieldID + 1
    Field.s = StringField(String, FieldID, Separator)
    If Left(Field, 1) = Delimiter And Right(Field, 1) = Delimiter
        Field = Mid(Field, 2, Len(Field) - 2)
    EndIf
    ProcedureReturn Field
EndProcedure

;
;
;
  Result.s = ""
  String.s = "1," + Chr(34) + "SAS/ETS 9.1 User's Guide. Volume 1" + Chr(34) + ",," + Chr(34) + "SAS Publishing" + Chr(34) + ",2004,108350,0,SAS/ETS.,005.36," + Chr(34) + "HA30.3.S274 2004eb" + Chr(34) + ",Available,$231.95,,1590472446',1590474120',"
  EnumCSVFields(String, #FALSE, ",", Chr(34))
  For i = 1 To 30
    Result + "Field " + Str(i) + " contains : " + EnumCSVFields(String, #TRUE, ",", Chr(34)) + Chr(10) + Chr(13)
  Next
  MessageRequester("Results", Result, #PB_MessageRequester_OK)

  Result.s = ""
  String = "http://www.google.com/search?hl=en&as_qdr=all&q=%22string%22+filetype%3Apb&btnG=Search&lr="
  EnumCSVFields(String, #FALSE, "&", Chr(34))
  For i = 1 To 30
    Result + "Field " + Str(i) + " contains : " + EnumCSVFields(String, #TRUE, "&", Chr(34)) + Chr(10) + Chr(13)
  Next
  MessageRequester("Results", Result, #PB_MessageRequester_OK)
My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
sonic3d
New User
New User
Posts: 9
Joined: Thu Oct 02, 2003 2:36 pm

Post by sonic3d »

Thanks again fweil!!

You really gimme a new idea.And also,great code you post.
I tried your code and it work well in most case.Only a little problem when process string like this one:

Code: Select all

1,"Advanced Topics in Database Research. Volume 4","Siau, Keng","Idea Group Publishing",2005,126093,0,"Database management.",005.74,"QA76.9.D3A38eb vol. 4",Available,$84.95,,1591404711',1591404738',
The third item which contain comma within quote will be parsed as two items.Still nice code you wrote.Thanks again!!! :wink:

Finally I decided to solve the problem in my original function.And now I have found a way to solve it.
Code changed to:

Code: Select all

Procedure.s GetCsvItemString(*FullString)
  StartPos.l = 0
  EndPos.l = 0
  RtString.s = ""
  QuoteChar.s=Chr(34)
  MyFullStr.s=PeekS(*FullString,2048)
  If (QuoteChar=Left(MyFullStr,1))
    StartPos.l=2
    EndPos.l = FindString(MyFullStr,Chr(34)+",",2)
    RtString.s = Mid(MyFullStr,StartPos.l,EndPos-StartPos)
    MyFullStr = Mid(MyFullStr,EndPos+2,Len(MyFullStr)-EndPos+1-2)
  Else
    StartPos.l=1
    EndPos.l = FindString(MyFullStr,",",1)
    RtString.s = Mid(MyFullStr,StartPos.l,EndPos-StartPos)
    MyFullStr = Mid(MyFullStr,EndPos+1,Len(MyFullStr)-EndPos+1-1)
  EndIf
  PokeS(*FullString, MyFullStr, 2048)
  ProcedureReturn RtString
EndProcedure
The key part is changing

Code: Select all

If (Chr(34)=Left(MyFullStr,1))
into
QuoteChar.s=Chr(34)

Code: Select all

If (QuoteChar=Left(MyFullStr,1))
and the similiar thing may happened on compare with other special chars.
For example:

Code: Select all

Procedure.l LoadCsvItem2()
  CurrLineText$="hello"
  While ("" <> CurrLineText$)
  Wend
  ProcedureReturn CsvItemCount
EndProcedure
Call this function will cause return address restore error.It must be changed to

Code: Select all

Procedure.l LoadCsvItem2()
  CurrLineText$="hello"
  EmptyChar.s=""
  While (EmptyChar <> CurrLineText$)
  Wend
  ProcedureReturn CsvItemCount
EndProcedure

I believe this is a bug of PB 3.93
Post Reply