Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 04/11/24 in all areas

  1. Brandon Staggs

    Do you need an ARM64 compiler for Windows?

    Microsoft has been "increasing the pressure" on non-WinTel32 development for a decade. I remember thinking Embarcadero needed to hurry up and give me an option to target Windows Phone. Then to get serious about WinRT for Windows 8. Etc. Windows on ARM may indeed eventually matter, but I can hardly fault Embarcadero for taking a "wait and see" approach to the latest-and-greatest non-Win32 "pressure increase" from Microsoft.
  2. FreeDelphiPascal

    Delphi and "Use only memory safe languages"

    Nice post David S! I had recently to fix a bug in a program that was sending wrong financial reports to a governmental financial institution (equivalent to RSI in America) for 18 years. After 18 years, somebody observed the problem. It ended up that there was not only one bug, like 15. Nobody ever observed the other 14 instances where data was wrong. I was told to shut up and move on. Also, nobody cared that my new program was running 100x faster than the previous one. I told them that probably there were another 100 bugs in there (pascal-like code, no objects, thousands of warnings and hints - at least, there were no pointers!). They wouldn't let me rewrite the program. They said, it now it works, let it as it is. So people, don't blame Delphi for not being totally memory-safe. It is mostly the programmer that dictates the safety of a language. I guess the programmer that wrote that program in Delphi would be able to sneak in some calamities like this also in a language like Rust. __________ Also, many people complained about buffer overflow here. Turn on the damn Range and Overflow checking. It will catch a good bunch of those overflows - unless the devil thought you to use pointers all over the place.
  3. FreeDelphiPascal

    Delphi and "Use only memory safe languages"

    obj := TObject.Create; FreeAndNil(obj); FreeAndNil(obj); ------------------------------ On SO somebody wrote an example like this to prove how unsafe Delphi is: s: String; i: Integer; begin s:= 'four'; for i:= 1 to 1138 do begin write( s[i] ); // What will it access after i=4? end; end; At one point, we should stop talking about how safe the programming language is and start talking about how "unsafe" is the programmer 🙂 🙂
  4. David Heffernan

    Delphi and "Use only memory safe languages"

    I don't really understand this. I always write the try/finally immediately after the construction, and always bang the Free in immediately. Then I fill out the body. It's just a habit that you form so that you don't make such mistakes. And honestly, this is never one that is hard to debug because you just have a leak. And presumably you use leak detection tools so that you'd always find them immediately. I don't really understand this scenario either. If you have a reference to something that may or may not exist, you would test Assigned() before using it. And when you were finished, you'd set the reference back to nil once you'd destroyed it. The scenario that is tricky is when you have multiple references to an object.
  5. David Heffernan

    Delphi and "Use only memory safe languages"

    It's odd you say that, but I never have to debug issues like this. There are two simple patterns for lifetime and they are so ingrained, nobody ever makes a mistake in my team.
  6. Kas Ob.

    Delphi and "Use only memory safe languages"

    Fair and with in your right, but let me ask you a simple question When you last time saw Delphi/Pascal code where a function had one letter name like f or g ?... Yesterday i watched this I believe i pasted the link as Stefan put it in the German forum The talk is great and very valuable, and if anyone is not familiar with lecture then know that this dude wrote C++ specification for breakfast, and here it comes write the guide lines for safety, yet when i watched it i saw that he himself with his examples violate a rule that always use expressive naming, and yes there was f and g, this comes from math, and the obsession of C++ developer with math to look cool, everyone looks to Bjarne and his talks and books, yet the beginners will scratch these examples in their brains forever with one letter function as name. Look at this "New Rules" titled in 2020 https://devblogs.microsoft.com/cppblog/new-safety-rules-in-c-core-check/ I think every C and C++ compiler out there does warn about default for a switch, yet that blog post deemed it a must to remind everyone with it, in Rust the code will not compile and C and C++ and in %90 no one will see it because there 458648567 another warning, some of these warnings makes sense but most of them don't, C and C++ are cursed with arrogance and stubbornness and its culture is beyond control, (my opinion) Rollo62 all what i am saying is even with all of this power of C++, it fails be the best language for long term security and safety, they (the most invested companies and teams and i trust they have better insight and view on this subject ) said C/C++ will not cut it and Rust it is. they decided to burn the tower and throw the power tools for better language, that (again) doesn't bring any thing new, on the contrary only remove the ability to use many C++ features, and evidently they see it as success story.
  7. Kas Ob.

    Delphi and "Use only memory safe languages"

    Its not that only. See, we the Delphi programmers used to do things in specific way, this out of the structure of the language of Pascal and by tradition or best practices, it goes like (as example ) automatically without thinking to put try..finally then call free, C++ there is none like this, but i am not saying C++ is incapable of, on contrary it can do more things because it is more powerful, but C++ developers doesn't have the discipline of Pascal's, this is exactly why all these big companies with their top tier developer keep doing or falling with the same traps again and again. When these big companies suggest to switch to different language like Rust not out of powerful of Rust or the lack of the tools in C++, on the contrary they reached to a conclusion that too much power is simply harmful, more limited tools are better fit and more secure. When you say Delphi is not memory safe, yes it is, just like any other language, yet the guide lines for Pascal and Delphi are way simpler and clearer than C++ to produce memory safe code (either bugs or vulnerability) , Rust is similar, its guide lines are harder to break as they incorporated within the language syntax itself. In Delphi if you leave the Overflow Check at on all the time, then you really had to be making big mistakes to breach memory safety for something like accessing index memory or handling managed types, these managed types specially arrays and strings are managed by the compiler in very nice way, in C++ there is hundreds of implementation of such arrays and strings, and they all will depends on some implementation, yet while they are completely safe at the same type coming form the same library, they are useless when it comes to interact with different library or the OS or whatever and here comes the problems of casting and unsafe converting.
  8. Kas Ob.

    Delphi and "Use only memory safe languages"

    If C++ compiler allocated all vars upfront and didn't use PUSH/POP inside any scope of code then they will be closer.
  9. Rollo62

    Delphi and "Use only memory safe languages"

    Exactly, that's why I laughed about that whole discussion, because the core question is pretty clear. Maybe I should add an <irony> tag, to make that more clear to everybody. The core question: Delphi is NOT memory-safe ... period. If some institutions think otherwise, and Embarcadero likes to use that statement for marketing purposes, ... so what?! Do you expect Embarcadero shall deny and contradict such an official statement from the government? Probably not, I wouldn't do either. Let's embrace these statements and use them as marketing for Delphi too. Every help from inside and outside is welcome, IMHO.
  10. JonRobertson

    Delphi and "Use only memory safe languages"

    I do, and I suspect many others do as well. What I was mostly disappointed about was the statement below. The company promoted in that link and the accompanying webinar was DerScanner. I watched the webinar last September and it intrigued me enough to ask approval to pursue having a small project analyzed and review the results. Their home page had a short form to request a trial. Instead of providing a trial, I received an email that I will share, since it is typical marketing: I responded that I requested a trial from their home page. The reply was that my request for a trial was forwarded and included a whitepaper that "describes the key features of DerScanner". One of the key features was that DerScanner could analyze 36 programming languages, "even obsolete Delphi, COBOL and Visual Basic 6.0". I also noticed that the short form on their home page was changed from a trial request to "Get a Demo". They did provide a trial account and I submitted the project along with a couple third-party libraries (with each vendor's permission). The resulting report contained thousands of incorrect analysis. One of the more prominent and obnoxious was “hardcoded encryption key”, for code such as "ctrlKey := GetKeyState(VK_Control) < 0", and every other line of code that contained these three characters in sequence: k e y, including static text. The analysis that DerScanner provided was a complete joke and a total waste of time. The trial included two scans for free (I only used one), additional scans after the trial were $1,000 per scan. Sure, my employer can say "Yes, we are concerned about security. We had our application analyzed by a third-party that specializes in code analysis. They used a highly sophisticated tool named grep to analyze our code for vulnerabilities." I am particularly disappointed in the recent statement because I had direct contact with Ian regarding my frustrating experience, and the laugh that I had after reviewing the generated report.
  11. Ian Branch

    Delphi and "Use only memory safe languages"

    Oh how true.....
  12. David Schwartz

    Delphi and "Use only memory safe languages"

    Sorry, y'all are obviously not reading my mind correctly. I was not referring to simple Pointer Aliases. TL;DR -- Pointer aliases are inconsequential. Pointer math is extremely hazardous. In my experience, companies couldn't care less about making code run faster ... not a "little bit" (minutes saved) nor a "huge amount" (hours saved). Nothing justifies using pointer math in Delphi apps to make apps run faster due to the likelihood of errors that the compilar nor test suites can catch. Desktop apps are far different from real-time process control apps, or even the libraries used in them; NOBODY cares about making them run "a little faster" that a newer faster computer won't fix I was referring to constructs like this (and I may not have even used them properly): ---------------------------------------------------------- var pXyz : pointer; <---- var xyz: integer; pXyz := ^xyz; <---- var i : integer; var myIntAry : array [0..maxVal] of Integer; for i := Min(myIntAry) to Max(myIntAry) do begin // this is an example of what I was referring to that's used frequently in C and C++ ^pXyz := Random(1000); inc(pXyz); end; ---------------------------------------------------------- ((sorry, the insert Code thing isn't working)) Yes, I realize Pointer aliases are used a lot in the VCL source code, but most of that was written in the 1990's and probably hasn't been updated much since then. ("If it ain't broken, don't fix it.") I also realize that Delphi class vars (eg, myClass : TMyClass) are basically pointers treated as references (like C++: TMyClass : &myClass = new(TMyClass); ) The pointers of concern (that use the ^ operator the same way C/C++ uses the * operator) are also the code used any time you have a Record that's allocated from the heap. The thing is, some people still obsess over a few extra instructions that the compiler might generate that can be eliminated using pointers, but I suspect most of them are "old school" programmers from way back in the day when every CPU cycle and byte of memory that could be saved were significant. When programs were 50k, they could be copied to a 128k floppy for distribution, and nobody ever imagined a computer would need more than a few MB of RAM. I was taught that way, but shook off that habit in the 90's. Today, desktop computers ship with 8 GB or more of RAM. (My first HDD was a whopping 10 MB!) The CPUs are multi-core and have hyper-threading, and if you try to out-guess the compiler's optimizer, the code is more likely than not to run slower due to all of the NOPs injected into the instruction cache. All of that hand optimization is likely to work on only ONE CPU (or CPU family) and will need to be revised for every difference in number of cores, instruction cache size, and maybe even data cache size. I know there are always "exceptions". MOST people creating form-based desktop apps that interact with a back-end database using Delphi are NOT writing code like that! They _might_ declare a pointer alias here and there, but they certainly aren't writing code that anybody will notice if it runs 100ms faster. At my last job, I was told to "port' something that was written for use by one specific client. It ran once a day and took a bunch of daily invoices scanned into PDF files at a dozen or so sales offices, with hundreds of pages saved into each PDF. It ran some OCR on each page and attempted to read an Invoice# from each one and then put the pages for each invoice into a separate PDF so the customer could view the pages for each invoice online if they wanted to, with all of the pages for that invoice in a single PDF file. It used a Version 1.0 DLL from an OCR app from 1997 that ran under WIndows 98 when it was released. This was 2018 and the code didn't run properly under Win10. For years, this thing ran in an hour or so. When I got hold of it, it took 8 hours to process a thousand or so invoices daily. I also discovered that it was unable to process about 30% of the invoices it was given and simply skipped over them. I completely rewrote it using a much newer OCR library written in Delphi, and my version ran in about 45 minutes for the same data that took the older one >6 hours. NOT ONE PERSON CARED THAT IT RAN SO MUCH FASTER! NOT EVEN THE CLIENT! In fact, my boss made a note on my annual review that this task took me 2 months to complete while they believed should have taken a week or two. (Never mind that their analysis was totally off-base.) The client rep contacted our support wondering why there were suddenly so many more invoices showing up every day in the process summary. I told our internal support person it was because the old code was not processing about 1/3 of them. When she told the client, they said, "Oh, ok. That's good to know." That was it. In use for over 15 years, they never noticed anything was wrong. This is hardly an isolated experience I've had over the past 25 years writing and maintaining Delphi desktop apps for clients. Nobody really cares about even significant performance issues, and most don't notice small problems. Very few ever audit their data, either. I worked at one place and discovered that medical invoices were being printed out and some separator pages were missing, and so customers were being mailed health records for other people accidentally stuffed into their envelopes, and nobody at our company that did the printing and mailing, nor the client company, ever knew! This should have been treated as a MAJOR HIPAA violation, but I was told to keep my mouth shut and just fix the problem. You guys outside of America might be wondering how this happens, but from my experience, it's quite common. Every job and contract I've had, I've found at least one and sometimes dozens if not hundreds of things that had been operating improperly for years. Some were performance-related, but most were just data integrity problems. Management mostly did not want to hear about it. So I really don't want to hear about all of the exceptions and reasons why it's important to shave 50 ms off of the execution time of some loop you may be working on. The last place I worked printed bills and invoices, stuffed them into envelopes, and sent them out to the US Post Office -- 7 or 8 full 40' semi-trailers EVERY DAY, 7 days a week. They got pissed off if part of a line on an invoice was cut off on a print run of 50,000 invoices; not whether it took an extra 15 minutes to run a given print job, as long as the people who got the materials could read them and they looked "professional". If customers didn't complain, that meant nothing was wrong. Nobody cared what we programmers might find. One thing I've found over the past 15 years is that Management is far more scared of allowing programmers to refactor code than just about anything else. Because trying to shave a few seconds of processing time often leads to bugs that did not exist previously. And yes, that's because they don't have comprehensive test suites (which are notoriously hard to write for form-based Delphi apps).
  13. Kas Ob.

    Delphi and "Use only memory safe languages"

    I mentioned or to be exact dreamed about more evolved Pascal enhancement, mentioned it here at once as i recall, but really can't remember any comments or any discussions. So will write it here as it is relevant for memory safety. My suggestion is to introduce new modifier(s) to managed (and non managed) variables, this include classes/objects, the new main modifier is "Auto", example procedure Test(aFileName: string); var SList: TStringList; auto; // the compiler will ensure calling the default constructor and destructor begin //SList := TStringList.Create; // should stop the compiler with specific Error, you are not allowed to create an auto SList.LoadFromFile(aFileName); //SList.Free // should stop the compiler with specific Error, you are not allowed to destreuct/free an auto end There is also similar modifier like "init/create" and "free" these will only their part and the compiler will ensure you can't abuse the memory layout or use after free. This also can be applied to fields in TObject/Class, the compiler will put the default constructor and destructor in their right position and will stop compiling when the code is trying to call constructor and destructor. But one could say using "auto" for the fields in classes will make initializing slower, no it will not as sooner or later it will initialized or used (except other usage, will follow down), will this cause degradation in performance?, no, not really, after all there is a price for pay. Another modifier which i can argue will be very helpful, is "delayed" or "onuse".., this one is for places when you don't know if that class will be needed or not, so the compiler will not auto create it !, but will initialize it to 0 (nil), and will check against that nil on every first usage with in the current scope then call the constructor in-place, guaranteeing its readiness, while will enforce calling the destructor in every scope it mentioned (referenced) but again if it is nil then nothing to do. With "delayed" modifier there is a performance hit for sure but it is merely "if assigned(x)" and as i mentioned above at the first usage in the current scope, so when in doubt i will leave to the compiler but when i am sure i will need that delayed to be ready for lets say a loop, then i can call specific function on it or just touch it in any code so the following code will not have to have the check for creation, of course if such delayed var is used in a loop then the compiler will put the constructor before entering the loop (at the loop limit preparing code) Also to mention how clean the code will become not just eliminating user after free or use non initialized. as for compiler: Delphi compiler is already equipped and has the ability to do that so minimal adjusting is needed, it does the same with all managed types (strings, arrays..) for the suggested modifiers above it will be close to this Currently the compiler does the same with strings and arrays as seen here ( though this is my XE8 so not sure about the latest versions) for combining the suggested "delayed" with the above the compiler could check for referencing one to another and adjust or rearrange the creation and destruction order. Anyway, this i this another short by me to reach a discussion about this enhancement or call it evolution, also this is the right evolution toward more memory safety. There is also can be a suggestion for different modifier "secure" "mute" (or something), with this one the compiler will allow any assigning to referencing (or double referencing), in other words and as example, X is a class, no code such Y := X is allowed, you need X (the object in X) you have to use it where is it which is X, This will ensure specific design and will limit pointer miss using, you want to load a bunch of the like of that X in an array then either declare them there with in the array and use them there, or, custom and precise steps should be done as guarantee to the compiler that this is well thought of, otherwise we need to write better code and design the structure better, another example ; X is secure object and it is a field in the non secure Z, the compiler will not allow to use X out side the scope of this current scope and/or outside the Z, meaning, the compiler will not allow passing X as parameter to a procedure, but will allow Z, X and its value is not allowed to be used in any direct assigning ":=", still we have the ability to introduce assign as operator that will ship or duplicate X fields, but not X itself or its pointer, that pointer should not be reached or allowed to be accessed by the compiler, and when i say compiler i mean the new language constraints for these suggestions.
  14. Anders Melander

    Quality Portal going to be moved

    That's not quite true. Jira Server is EOL in february this year but there's still Jira Data Center which is also on-prem (and extremely expensive). So the question is what "limited" means. Jira is licensed per-user and I'm guessing that they're not going to buy a license for each of their Delphi users. Instead they might be going with Jira Cloud internally and Jira Service Management (JSM, formerly Service Desk) externally. JSM is licensed per agent (internal user) with unlimited externals users (called "external customer" in JSM). I trialed JSM many years ago for external support but back then it was still licensed per external user and didn't really work that well, compared to something like ZenDesk. As far as I know JSM does not allow one external user to see the issues raised by other external users. I.e. it's a support system; There's no interaction between external users. So if JSM is the solution they are going for I don't see it as an improvement. As I customer I don't really care about what goes on behind the curtain. From my POW it seemed to work fine but I guess you point was that it only seemed that way. I wish I could have your admirable optimism.
  15. I solved this thanks to the kind collaboration of the nSoftware assistance service (SecureBlackBox's developer). There were many challenges to solve to achieve the goal and very little can be found online. It is my understanding that this type of security is not used much in the Delphi environment. However I solved by combining several components provided with the SecurityBlackBox suite: TsbxCertificateStorage to read JKS file to reach public key (used to encrypt the request and verify the signed response) and private key (used to sign the request and decrypt the response) TsbxSOAPSigner to sign the SOAP request (to produce a WSSSignature) TsbxXMLEncryptor to embed in the request the encryption key (transported with RSA-OAEP sha1) and to crypt the SOAP request body (with AES128 algorithm) TsbxXMLDecryptor to decrypt the response (two items encrypted in the response: the sign and the body) TsbxSOAPVerifier to verifiy the sign in the response I've injected this encryption/decryption stuff in THTTPRio events, somthing like this; procedure TMultyAssociativeServiceWrapper.SOAPOnBeforeExecute(const MethodName: String; SOAPRequest: TStream); begin // save the original request (created by THTTPRio) for debug purpose SOAPRequest.Seek(0,0); (SOAPRequest as TMemoryStream).SaveToFile(FFileRequestOriginal); // sign and encrypt the original request SBBSoapSignAndEncryptWithJKS(FFileRequestOriginal, FFileRequestToSend, FCertificateFileJKS, OnPasswordNeeded); // ... do some other stuff ? // update the outcoming request with the signed crypted version SOAPRequest.Seek(0,0); (SOAPRequest as TMemoryStream).LoadFromFile(FFileRequestToSend); end; procedure TMultyAssociativeServiceWrapper.SOAPOnAfterExecute(const MethodName: String; SOAPResponse: TStream); begin // save te orginal response arrived from service for debug purpose SOAPResponse.Seek(0,0); (SOAPResponse as TMemoryStream).SaveToFile(FFileResponseOriginal); // decrypt and verify sign of response SBBSoapDecryptAndVerifyWithJKS(FFileResponseOriginal, FFileResponseDecoded, FCertificateFileJKS, OnPasswordNeeded); //... do some other stuff? // update the incoming response with the decrypted data SOAPResponse.Seek(0,0); (SOAPResponse as TMemoryStream).LoadFromFile(FFileResponseDecoded); end; SBBSoapSignAndEncryptWithJKS does sign + encryption stuff. SBBSoapDecryptAndVerifyWithJKS does decrypt and verify sign stuff. I hope this can be helpful for someone else who runs into this need. If you need the code of the two SBB procedures described above please ask me. I've used SecureBlackBox components but I think that same stuff could be reached also with ChilKat library. I did some tests with the demo library, it works at a lower level of SBB but there are several examples online that could be combined to reach the goal.
  16. Stefan Glienke

    Check for override

    "Backwards compatibility" is the ultimate excuse to pile up garbage in your backyard ... It is used or ignored whenever convenient - moving forward also includes getting a compile error in your face but with a clear guide at hand how to solve it. If you ever inherited from a TDataSet and used one of its method that have TBookmark or TRecordBuffer arguments while writing code for different Delphi versions since 2010 or so you know what I mean. But some developers seem to rather want to save an hour when moving their code to a new version and waste hours or days later hunting down a bug. 😉
×