Constructed Regexes in a CLR Application


We are going to use WinDbg to peek into a sample application to see which regex patterns are being used.

Required Environment

  • WinDbg as a part of Debugging Tools For Windows, which can be found here.
  • Set symbol path using the .symfix command.
  • Network access to Microsoft Symbol Server.
  • Sample application that uses .NET regexes, which can be downloaded from the github repository krk/regextest.


This article is not about introducing WinDbg, SOS or .NET flavored Regexes. Only short descriptions are provided.

What is WinDbg?

WinDbg is a powerful debugging tool from Microsoft that you get with a Windows license. WinDbg is a native debugger with extensions support.

What is SOS?

SOS or Son-of-Strike is a WinDbg extension that helps the debugger to traverse the CLR data structures in memory with ease to facilitate managed debugging. SOS.dll uses the Data Access Component in mscordacwks.dll to access the .NET data structures.

In order to debug managed code, exact version match of these dlls is needed between the debugging machine and the machine where the dump is taken. It is usually a good idea to pack SOS.dll and mscordacwks.dll together with the memory dump file.

What is a regular expression?

A regular expression is a pattern string that matches an input string when evaluated with respect to the regular expression grammar of the library or the host language, e.g. PERL, python, .NET Regex. In the context of .NET, a regex means an instance of the type System.Text.RegularExpressions.Regex.


WinDbg will be used to break on Regex class constructor invocations to log the pattern which is passed as a parameter to the Regex class.

Setting up your environment

Start WinDbg (X86) and load the sample executable called RegexTest.exe.

Press Ctrl+E to open the executable:

ModLoad: 00520000 00528000 RegexTest.exe
SHIMVIEW: ShimInfo(Complete)
(22a0.182c): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=fa190000 edx=00000000 esi=7e797000 edi=00000000
eip=77283bed esp=006af664 ebp=006af690 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
77283bed cc int 3

Fix symbols if needed:

0:000> .symfix c:\symbols
0:000> .reload
Reloading current modules

Load the Son-of-Strike extension sos.dll. SOS must be loaded after CLR is loaded. For .NET 2.0, use mscorwks instead of clr

0:000> sxe ld clr.dll
0:000> g
ModLoad: 73f40000 745da000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
eax=00000000 ebx=00800000 ecx=00000000 edx=00000000 esi=00000000 edi=7e79e000
eip=7720c6fc esp=006af2a0 ebp=006af2fc iopl=0         nv up ei pl nz ac pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000216
7720c6fc c22800          ret     28h
0:000> .loadby sos clr

Break on loading of to set a breakpoint on the .NET entry method.

0:000> sxe ld
0:000> g
(22a0.182c): Unknown exception - code 04242420 (first chance)
ModLoad: 722a0000 72c20000   C:\Windows\assembly\NativeImages_v4.0.30319_32\System\2482799f892ac9e635f6e1453f0dfdd5\
eax=00000000 ebx=00800000 ecx=00000000 edx=00000000 esi=00000000 edi=7e79e000
eip=7720c6fc esp=006aa620 ebp=006aa67c iopl=0         nv up ei pl nz ac po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000212
7720c6fc c22800          ret     28h

Find the entry method address which can be found with ILSpy or a similar IL decompiler. In our case, it is the Program.Main method.

0:000> !name2ee RegexTest.exe Program.Main
Module:      007a3fbc
Assembly:    RegexTest.exe
Token:       06000001
MethodDesc:  007a4cc4
Name:        RegexTest.Program.Main(System.String[])
Not JITTED yet. Use !bpmd -md 007a4cc4 to break on run. <- We use this address

Break on the Main method using the bpmd SOS extension.

0:000> !bpmd -md 00c54cc4
MethodDesc = 00c54cc4
Adding pending breakpoints...
0:000> g
(16ec.1dc4): CLR notification exception - code e0444143 (first chance)
JITTED RegexTest!RegexTest.Program.Main(System.String[])
Setting breakpoint: bp 00D9049C [RegexTest.Program.Main(System.String[])]
Breakpoint 0 hit
eax=00000000 ebx=00b5f4dc ecx=02992350 edx=00000000 esi=02992350 edi=00b5f424
eip=00d9049c esp=00b5f3a4 ebp=00b5f438 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
00d9049c 90              nop

We are safe to assume that all Regex constructors call the private Regex ctor which has 4 parameters. We list all Regex ctors and set a breakpoint on the private ctor.

0:000> !name2ee System.dll System.Text.RegularExpressions.Regex..ctor
Module:      722a1000
Assembly:    System.dll
Token:       06003c8b
MethodDesc:  722a37f8
Name:        System.Text.RegularExpressions.Regex..ctor()
JITTED Code Address: 7242a690
Token:       06003c8c
MethodDesc:  722a3800
Name:        System.Text.RegularExpressions.Regex..ctor(System.String)
JITTED Code Address: 72441804
Token:       06003c8d
MethodDesc:  722a380c
Name:        System.Text.RegularExpressions.Regex..ctor(System.String, System.Text.RegularExpressions.RegexOptions)
JITTED Code Address: 72439850
Token:       06003c8e
MethodDesc:  722a3818
Name:        System.Text.RegularExpressions.Regex..ctor(System.String, System.Text.RegularExpressions.RegexOptions, System.TimeSpan)
JITTED Code Address: 72851118
Token:       06003c8f
MethodDesc:  722a3824
Name:        System.Text.RegularExpressions.Regex..ctor(System.String, System.Text.RegularExpressions.RegexOptions, System.TimeSpan, Boolean) 
JITTED Code Address: 7243bd60 <- We need this constructor address.
Token:       06003c90
MethodDesc:  722a3838
Name:        System.Text.RegularExpressions.Regex..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)
JITTED Code Address: 72851134

Set a breakpoint on the private constructor which is used by all public constructors.

0:000> bp 7243bd60
*** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v4.0.30319_32\System\2482799f892ac9e635f6e1453f0dfdd5\
0:000> g
Breakpoint 1 hit
eax=723d4680 ebx=00b5f4dc ecx=02992450 edx=02992438 esi=02992438 edi=02992450
eip=7243bd60 esp=00b5f380 ebp=00b5f39c iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
7243bd60 55              push    ebp

JIT seems to use the fastcall convention [citation needed] and passes a pointer to the this instance as the first parameter which is in ecx so our string pattern parameter should be in edx.

0:000> !do edx
Name:        System.String
MethodTable: 730e0938
EEClass:     72d1dd18
Size:        22(0x16) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      aaa1 <- This is the first regex generated by the sample application.
      MT    Field   Offset                 Type VT     Attr    Value Name
730e27c0  4000243        4         System.Int32  1 instance        4 m_stringLength
730e137c  4000244        8          System.Char  1 instance       61 m_firstChar
730e0938  4000248       40        System.String  0   shared   static Empty
    >> Domain:Value  00e27888:NotInit  <<

Get the unicode string associated with the String object.

0:000> .printf "Regex: %mu\n", 8+edx
Regex: aaa1

Now we clear the previous breakpoints and automate the task and log all regexes to a file.

0:000> bc *
0:000> bp 7243bd60 ".printf \"Regex: %mu\\n\", 8+edx ;g"
breakpoint 1 redefined
0:000> .logopen /u c:\logs\regex.txt
Opened log file 'c:\logs\regex.txt'
0:000> g
Regex: aaa2
Regex: aaa3
Regex: bcd1
Regex: bcd2
Regex: bcd3
Regex: ceg1
Regex: ceg2
Regex: ceg3
Regex: dgj1
Regex: dgj2

When the application exits or you press Ctrl+Break, call .logclose and your regex log file will be ready to be consumed.

0:000> .logclose


GitHub repository for the sample application is

Curious Case of Code Contracts and Roslyn


We have a large visual studio solution that uses Microsoft CodeContracts for run-time verification and static analysis. Code contracts is a great tool that proves there are bugs in your source code. When it is hard to deduce for the static analyzer to prove facts, you can always help by adding contract blocks in your source code. In addition to static analysis, using a contract statement such as

Contract.Requires(count > 0);

will throw an exception at the runtime. Code contracts extension includes an IL weaver engine that rewrites the Contract statements to a statement that performs the runtime check and reports an error that includes the predicate as a string:

__ContractsRuntime.Requires(count > 0, null"count > 0");

There are many other aspects of the Microsoft Code Contracts that your solution can benefit and they have an extensive documentation.


On the other hand we have Roslyn installed as the default compiler service within Visual Studio 2013. Rest all other pros, navigating within Visual Studio is many times faster now with Roslyn.


… is that when you have a method which has dynamic local variables, code contracts rewriter (ccrewrite.exe) throws an internal exception which leads to an error message similar to:

1> There were errors reported in {0}'s metadata.
1> Unknown custom metadata item kind: 5

Upon investigating one can find out that Code Contracts project is snail-speed with its updates and it takes time to catch the changes. In this case, code contracts is lagging behind Roslyn in terms of PDB (program database) reading and writing.

After searching for the string “Unknown custom metadata item kind:”, we arrive at the method ReadCustomMetadata in PdbFunction class in CCI project which code contracts uses to handle PDB files. Thus we can no longer blame Code Contracts project lagging behind Rosyln, it is Common Compiler Infrastructure: Metadata API which is not up-to-date.

private void ReadCustomMetadata(BitAccess bits) {
  int savedPosition = bits.Position;
  byte version;
  bits.ReadUInt8(out version);
  if (version != 4) {
    throw new PdbDebugException("Unknown custom metadata item version: {0}", version);
  byte kind;
  bits.ReadUInt8(out kind);
  uint numberOfBytesInItem;
  bits.ReadUInt32(out numberOfBytesInItem);
  switch (kind) {
    case 0: this.ReadUsingInfo(bits); break;
    case 1: this.ReadForwardInfo(bits); break;
    case 2: break; // this.ReadForwardedToModuleInfo(bits); break;
    case 3: this.ReadIteratorLocals(bits); break;
    case 4: this.ReadForwardIterator(bits); break;
    default: throw new PdbDebugException("Unknown custom metadata item kind: {0}", kind);
  bits.Position = savedPosition+(int)numberOfBytesInItem;

When an unhandled metadata kind is encountered, the method throws a PdbDebugException which is what we are seeing in the error message of ccrewrite.exe. We can try to handle this code or maybe we can get around just by not throwing the exception at all.

For example code that does not build see


We chose the road taken in this case, modifying switch statement to ignore unknown metadata kinds. To modify the switch statement, we need an IL editor such as ildasm/ilasm or reflexil. I will skip the modification step for brevity and highlight the removed part of the ReadCustomMetadata method:

private void ReadCustomMetadata(BitAccess bits)
	int position = bits.Position;
	byte b;
	bits.ReadUInt8(out b);
	if (b != 4)
		throw new PdbDebugException("Unknown custom metadata item version: {0}", new object[]
	byte b2;
	bits.ReadUInt8(out b2);
	uint num;
	bits.ReadUInt32(out num);
	switch (b2)
	case 0:
	case 1:
	case 2:
	case 3:
	case 4:
		throw new PdbDebugException("Unknown custom metadata item kind: {0}", new object[]
	bits.Position = position + (int)num;

Now we need to make the same modification in other applications, namely ccdocgen.exe, ccrefgen.exe, ccrewrite.exe files in addition to cccheck.exe. We can see that our modified code contracts can handle Roslyn generated PDB files that have a dynamic local without any visible problems, hence solving the problem.

1> “C:\Program Files (x86)\Microsoft\Contracts\Bin\ccrewrite.exe” “@{0}ccrewrite.rsp”
1> elapsed time: 199.3108ms
1> Touching “obj\Debug\{0}.rewritten”.

Windows Servislerinin İnternet Olmayan Sunucuda Çalışmaması

Bu yazımızda kendi yazdığımız windows servislerinin çalışmamasında yapılabilecek bazı kontroller ve bu kontroller işe yaramadığında yapılabilecek işlemler yer almaktadır.

“Lokalde çalışıyor”, “önceden çalışıyordu”, “başka sunucuda çalışıyor” önermelerine karşı kanıt yoluyla yanlışlama ve sorunun tespiti ile çözümü hakkında kısa bir yazı.


Bir sunucuya yeni kurulan windows servisi çalışmıyor. Servis yöneticisinden ilgili servis başlatılmak istenildiğinde zamanaşımına uğrayarak hata veriyor.

Şüphe I

Servis başladığında veritabanına hangi ayarlar ile başladığını kaydediyor. Servisin başlarken ilk yaptığı işlerden biri veritabanı ile ilgili bir işlem olduğundan ve bahsedilen kaydın da veritabanında bulunmamasından dolayı ilk olarak veritabanı erişiminden kaynaklı hata olduğu şüphesi oluştu. Daha önce aynı veritabanına ulaşan kullanıcı nasıl olur da erişemez hale gelirdi gibi soruları sormamak gayet doğaldır. Müşteri tarafından yapılabilecek işlemlerde sınır aramamak gerekir. Kullanıcı değişmiş haber verilmemiş olabilir, şifre değişmiş haber verilmemiş olabilir, veritabanı değişmiş haber verilmemiş olabilir, integrated authentication kullanıldığı için windows kullanıcısının şifresi zamanaşımına uğramış, değişmesi gerekiyor olabilir. Neyse ki bu gibi şüpheleri elemek nispeten kolay bir takım işlemler gerektiriyor.

Veritabanında sorun olmadığı tespit edildi, kullanıcılar ile ilgili değişen bir detaya da rastlanmadı.

Şüphe II

Veritabanında sorun yoksa ve servisin ilk yaptığı işlerden biri veritabanına bağlanmak ise servisin başlayıp durmasından çok hiç başlamamış olmasından şüphelenmek gerekir.

Servislerimiz bir preprocessor tanımı sayesinde “Debug” konfigürasyonunda derlendiğinde komut satırı uygulaması olarak, “Release” konfigürasyonunda derlendiğinde ise windows servisi olarak bir imaj(exe dosyası) oluşturuyor. Servislerin yanlışlıkla “Debug” modunda derlenerek sunucuya kurulduğu şüphesi oluştu.

Yapılan dosya karşılaştırma kontrollerinden sonra sunucudaki windows servisi uygulamasının “Release” konfigüyasyonunda derlenerek sunucuya yüklendiği tespit edildi.

Şüphe III

Kainattan şüphelenildi, fazla zaman kaybetmeden işletim sisteminden şüphelenildi. Uygulama çalışıyor muydu yoksa proses dahi oluşturulamadan hata mı alınıyordu? Bu önermenin karşılığını bulabilmek için eski dostumuz “Görev Yöneticisi” yardımımıza koşuyor. Görev yöneticisi açıkken windows servisi ile ilişkili bir prosesin yaratıldığını, hata almadan hemen önce de öldürüldüğünü yakalayabildik. Bu durumda proses başladıktan sonra fakat kontrol .NET’e geçemeden önce alınan bir hata ile karşı karşıyaydık.

Tespit I

Windows servisi başlarken .NET’e geçmeden hata alıyor. Hatanın doğrudan uygulama kaynaklı olmadığı da “Şüphe II” başlığında tespit edilmişti. Prosesin hafıza dökümünün(memory dump) incelenmesine karar verildi.

Hafıza dökümünün alınması

Görev yöneticisinden ilgili prosese sağ tıklanarak “Full Memory Dump” alınır. Daha sonra dosya, Windows Debugging Tools yüklü olan, sunucudan ayrı bir bilgisayara aktarılarak incelenebilir. Sunucu 64-bit ise, incelemenin yapılacağı bilgisayarın da en az 64 bit olması gerekmektedir.

Yardımımıza koşacak olan uygulama, windows kernel debugger, namı diğer ntsd, namı diğer cdb. Arayüz sevenler windbg kullanabilir, biraz daha rahat ama yine de dosyayı açtıktan sonra komut satırında devam etmek gerekiyor. Bu noktadan sonra windbg, debugger anlamında kullanılmıştır.

Bellek Dökümünün İncelenmesi

SoS’u WinDbg’ye yüklemeden önce analiz edilen her bellek dökümünde kontrol edilmesi gereken alanları inceliyoruz.

Dosyayı WinDbg’ye yüklediğimizde aşağıdaki gibi bir ekran bizi karşılamalıdır.


Bellek dökümünü kotarılmamış istisnai durumdan(unhandled exception) oluşmadığı için, manuel olarak alındığı için doğrudan aktif thread’in call stack’ini inceleyebiliriz.

Aktif thread’in stack trace’ini görmek için kb yazıp entera basıyoruz.

Adreslere, parametre değerlerine ve metod içerisindeki satırlara dikkat etmeden akışı sezmeye çalışıyoruz. İncelediğimiz call stack, 4 farklı gruptan çağrı içeriyor. En üstteki NtWaitForSingleObject, en son girilen metodu gösteriyor, en alttaki RtlUserThreadStart ise bulunulan thread için ilk çalıştırılan metodu gösteriyor.

Stack traceini kabaca inceleyecek olursak:

  1. İlk grup koyu mavi, thread’i başlatıp kontrolü WinMain metoduna aktaracak olan işletim sistemi metodları. WinMain, .NET uygulamalarında hemen mscoree.dll içindeki CorExeMain metodunu çağırarak kontrolü .NET’e devreder. (Adına WinMain denmesine rağmen önemli olan adresi olduğu için adı farklı olabilir. )
  2. İkinci grup turuncular, .NET’in windows servisimizi çalıştırırken harcadığı çabaların bir kısmını içermektedir.
    1. CorExeMain’den sonra AppDomain yüklenir.
    2. ClassLoader, .NET Main entry point metodunun hangi sınıfta olduğunu bulup ilgili MSIL kodlarını derlemek ister.
    3. PreJit (JIT-derleme öncesi) Main metodunu derlemek üzere harekete geçer.
    4. Hangi assembly’de olduğu bulunan metod, hafızaya yüklenerek derlenecektir.
    5. Assembly hafızaya yüklemeden önce imza kontrolleri yapılır (DoLoadSignatureChecks) (Şüphe IV bu noktada oluşmaya başlıyor)
    6. mscorsec modülü, yayıncıyı bulmak ister. (GetPublisher)
  3. Üçüncü grup bordolar, mscorsec modülünün isteği üzerine yüklenen wintrust ve ardından gelen crypt32 ve cryptnet modüllerini içerir.
    1. Wintrust modülü, WinVerifyTrust metodu ile yüklenmek istenen assembly’lerin Authenticode imzalı olanlarının güvenilirlik kontorlü yapılır.  Authenticode, .NET’ten bağımsız olan, Microsoft’un exe ve dll’ler için sunduğu HTTPS/SSL olarak düşünülebilir.
    2. crypt32’de bir takım sertifika kontrolü görünüşlü metodların çağrıldığı aşikar.
    3. cryptnet modülü ise webden bir bilgi indirmeye çalışıyor. (Şüphe IV bu noktada oluştu)
  4. Dördüncü grup açık maviler, muhtemelen bir grup IRP(I/O Request Packet)’nin tamamlanmasını senkron olarak bekleyen cryptnet aksamlarına bağlılar.

0:000> kb RetAddr : Args to Child : Call Site 000007fe`fd5710dc : 000007fe`fdebc943 00000000`775c5133 00000000`0018bf68 00000000`00000000 : ntdll!NtWaitForSingleObject+0xa 000007fe`faf9a06a : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`000003f8 : KERNELBASE!WaitForSingleObjectEx+0x79 000007fe`faf976da : 00000000`00000000 000007fe`fafabc04 00000000`199a7520 00000000`00003a98 : cryptnet!CryptRetrieveObjectByUrlWithTimeout+0x263 000007fe`fd6948b0 : 00000000`04205004 00000000`00000000 00000000`04205004 000007fe`00003a98 : cryptnet!CryptRetrieveObjectByUrlW+0x20f 000007fe`fd6947de : 00000000`04205004 00000000`00000001 00000000`00000000 00000000`199a7520 : crypt32!ChainRetrieveObjectByUrlW+0x80 000007fe`fd71b5a1 : 00000000`19982a60 00000000`00000000 00000000`00000048 00000000`199a7520 : crypt32!CCertChainEngine::RetrieveAuthRootAutoUpdateObjectByUrlW+0x135 000007fe`fd71bd14 : 00000000`00000006 00000000`1997e7c0 00000000`00000000 000007fe`00000000 : crypt32!CCertChainEngine::WireRetrieveAutoUpdateCab+0x151 000007fe`fd6a9b14 : 00000000`00000000 00000000`0018c240 00000000`00000000 01cdc27c`e93fbf58 : crypt32!CCertChainEngine::GetTimeValidDisallowedCertAutoUpdateCtl+0xe8 000007fe`fd66f046 : 00000000`19982a60 00000000`1997e7c0 00000000`00000000 00000000`19947700 : crypt32!CCertChainEngine::GetChainContext+0x7e 000007fe`fd5e4f70 : 00000000`19982a60 00000000`1997e7c0 00000000`19984094 00000000`48000001 : crypt32!CertGetCertificateChain+0x100 000007fe`fd5e4ccf : 00000000`0018c3a0 00000000`00000000 00000000`0018c348 00000000`00000000 : wintrust!_WalkChain+0x2b2 000007fe`fd5e1f56 : 00000000`00000000 00000000`00000000 00000000`0018c620 00000000`0018c460 : wintrust!WintrustCertificateTrust+0xea 000007fe`fd5e1057 : 00000000`0018c620 000007fe`f9805d23 00000000`00000000 00000000`00000000 : wintrust!WTHelperGetFileHash+0x48e 00000642`ffaf7ed1 : 00000000`0028b7d0 00000000`00000003 00000000`00000000 00000000`00000000 : wintrust!WinVerifyTrust+0x70 000007fe`f7a98aac : 00000000`0028b7d0 00000000`00000000 00000000`00000003 00000000`0018c6f8 : mscorsec!GetPublisher+0x139 000007fe`f77e0ae7 : 00000000`1993c440 000007fe`f77ff322 00000000`00000000 00000000`0018c6f8 : mscorwks! ?? ::FNODOBFM::`string'+0x4499c 000007fe`f77cd94d : 00000000`0000002a 00000000`00000000 00000000`00000000 00000000`00000000 : mscorwks!PEAssembly::DoLoadSignatureChecks+0x37 000007fe`f77d9f80 : 00000000`1993c440 00000002`00000000 00000000`19951320 00000000`0028b6d0 : mscorwks!PEAssembly::PEAssembly+0x12d 000007fe`f77e6481 : 00000000`0000000b 00000000`002444a0 ffffffff`fffffffe 00000000`0025c9b0 : mscorwks!PEAssembly::DoOpen+0x11c 000007fe`f770afda : 00000000`19951320 00000000`0018cc88 00000000`00000000 000007fe`00000000 : mscorwks!PEAssembly::Open+0x71 000007fe`f76fb08a : 00000000`002434f0 00000000`0018cef0 00000000`00000001 00000000`19936ad0 : mscorwks!AppDomain::BindAssemblySpec+0x266 000007fe`f771ee20 : 00000000`1993c0c0 00000000`00000001 00000000`00000000 00000299`00160025 : mscorwks!PEFile::LoadAssembly+0xae 000007fe`f778df38 : 00000000`0025c9b0 00000000`00279170 000007fe`00000022 00000299`00160025 : mscorwks!Module::LoadAssembly+0x120 000007fe`f7768123 : 00000000`02000048 00000008`8f855083 00000000`0018d450 00000000`00000000 : mscorwks!Assembly::FindModuleByTypeRef+0xec 000007fe`f7787490 : 00000000`00000000 00000000`0018d558 00000000`010b6200 000007fe`00000000 : mscorwks!ClassLoader::LoadTypeDefOrRefThrowing+0x4a3 000007fe`f776e76f : 000007ff`00027cd8 00000000`00000001 00000000`0a000039 00000000`0018d880 : mscorwks!ClassLoader::LoadTypeDefOrRefOrSpecThrowing+0x58 000007fe`f776dfc4 : 000007ff`00029710 000007ff`00000006 00000000`010bc6bc 00000000`00000000 : mscorwks!MemberLoader::GetDescFromMemberDefOrRefThrowing+0x51f 000007fe`f776d698 : 00000000`00000001 00000000`0a000039 00000000`5df3edc8 000007fe`f774ca03 : mscorwks!MemberLoader::GetMethodDescFromMemberDefOrRefOrSpecThrowing+0xd4 000007fe`f77642d0 : 00000000`0018e2a0 000007ff`000296b8 000007ff`00000001 00000000`00000001 : mscorwks!CEEInfo::findMethodInternal+0x218 000007fe`f8037659 : 00000000`19e3b818 00000000`0a000039 00000000`0018de00 00000000`00000000 : mscorwks!CEEInfo::findMethod+0xf0 000007fe`f8030ab5 : 00000000`0018de00 00000000`00000028 00000000`0a000039 00000000`0000001e : mscorjit!GenIR::GenIR_FgCall+0x149 000007fe`f803ad43 : 00000000`19e20100 00000000`19e202d8 00000000`5df36074 00000000`0018de00 : mscorjit!ReaderBase::fgBuildPhase1+0x2a5 000007fe`f8018597 : 00000000`00000000 00000000`0018de00 00000000`00000000 00000000`00000000 : mscorjit!ReaderBase::fgBuildBasicBlocksFromBytes+0x93 000007fe`f7feed71 : 00000000`0018e2b8 00000000`19920540 00000000`00100010 00000000`010b8efc : mscorjit!ReaderBase::MSILToIR+0xa7 000007fe`f7fe51e0 : 00000000`0025c9b0 00000000`19951b90 00000000`00274f00 00000000`010b8886 : mscorjit!THX_dop2+0x2a1 000007fe`f77be279 : 00000000`1991d9b0 000007ff`00029710 000007ff`00029710 000007ff`000296b8 : mscorjit!PreJit::compileMethod+0xc0 000007fe`f77a94d2 : 00000000`19920540 000007ff`00029710 00000000`0018e400 00000000`00100010 : mscorwks!invokeCompileMethodHelper+0xd1 000007fe`f77a95c5 : 00000000`00000000 000007ff`000296b8 00000000`00000000 000007fe`00000000 : mscorwks!invokeCompileMethod+0x72 000007fe`f77963cb : 00000000`19920540 00000000`0018e2b8 00000000`00000003 00000000`00100010 : mscorwks!CallCompileMethodWithSEHWrapper+0xbd 000007fe`f7796a1a : 00000000`19930ed0 00000000`00000000 00000000`00000000 00000000`00000000 : mscorwks!UnsafeJitFunction+0x25b 000007fe`f7c30d5c : 000007ff`000296b8 00000002`00000000 00000000`00000000 00000000`00000000 : mscorwks!MethodDesc::MakeJitWorker+0x1ea 000007fe`f777de2a : 48cf9094`0b9ee7b6 00000000`0023d320 00000000`00000000 000007ff`000296b8 : mscorwks!MethodDesc::DoPrestub+0x54c 000007fe`f78c0167 : 00000000`01376fb8 00000000`012e2fa0 00000000`013777c8 00000000`0025c9b0 : mscorwks!PreStubWorker+0x1fa 000007ff`001a0829 : 00000000`013777c8 88cf90a4`cf27b7b6 00000000`00000002 00000000`00000000 : mscorwks!ThePreStubAMD64+0x87 000007ff`001a028f : 00000000`012e2fa0 00000002`18711a00 00000000`0018eba0 00000000`0136cf58 : 0x000007ff`001a0829 000007ff`001a0161 : 00000000`012e2fa0 000007ff`000233d0 00000000`0025fac0 00000000`000000d0 : 0x000007ff`001a028f 000007fe`f78c0282 : 000007ff`000239b8 000007fe`f7773d09 00000000`00000000 000007ff`000239a8 : 0x000007ff`001a0161 000007fe`f77a4363 : 00000000`00000000 000007fe`0000006b 000007fe`f7676a30 00000000`00000000 : mscorwks!CallDescrWorker+0x82 000007fe`f7c9b751 : 00000000`0018edb8 00000000`00000000 00000000`00000001 00000000`00000000 : mscorwks!CallDescrWorkerWithHandler+0xd3 000007fe`f780b097 : 00000000`00000000 000007ff`000239a8 00000000`00000000 00000000`0018f220 : mscorwks!MethodDesc::CallDescr+0x2b1 000007fe`f782e1fc : 00000000`00000000 00000000`00000000 00000010`009a0019 00000000`00000000 : mscorwks!ClassLoader::RunMain+0x22b 000007fe`f7d87a2d : 00000000`0018f810 00000000`00000000 00000000`0026b798 00000000`00000200 : mscorwks!Assembly::ExecuteMainMethod+0xbc 000007fe`f783bd17 : 00000000`00000000 00000000`00000000 00000000`00000000 000007fe`f7858442 : mscorwks!SystemDomain::ExecuteMainMethod+0x47d 000007fe`f781e1c4 : ffffffff`fffffffe 00000000`00000000 0000c275`00000000 00000000`00000000 : mscorwks!ExecuteEXE+0x47 000007fe`f9763309 : ffffffff`ffffffff 00000000`0025c9b0 00000000`00000000 00000000`0018fad8 : mscorwks!CorExeMain+0xac 000007fe`f97f5b21 : 000007fe`f781e118 000007fe`f97632c0 00000000`00000000 00000000`00000000 : mscoreei!CorExeMain+0x41 00000000`7736652d : 000007fe`f9760000 00000000`00000000 00000000`00000000 00000000`00000000 : mscoree!CorExeMain_Exported+0x57 00000000`7759c521 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d

Şüphe IV

Windows servisi başlatılırken bazı aksamlar internete erişmeye çalışıyor. Windows servisinin hata verdiği sunucuda internet erişimi olmadığı için hemen cevap alamayan aksamlar, kendi zamanaşımlarından önce service control utility(services.msc, sc.exe) uygulamasını zamanaşımına uğratıyor.

Tespit II

Windows servisi işletim sistemi tarafından başlatılırken uygulama ve referansları üzerinde Authenticode dijital imza kontrolü yapılırken internete erişmek istiyor. Bu erişim başarısız olduğundan CryptRetrieveObjectByUrlWithTimeout metoduna geçilen zamanaşımı süresi geçene kadar thread bu metoddan çıkamıyor.

Zamanaşımı süresi, varsa kayıt defterindeki HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ServicesPipeTimeout alanından gelecektir. Varsayılan kurulumlarda ServicesPipeTimeout  anahtarı yoktur ve Microsoft kaynaklarında bu değer için kesin bir rakam verilmemekle birlikte “30 saniyeden az” olduğundan bahsedilmektedir.

CryptRetrieveObjectByUrlWithTimeout metoduna geçilen timeout süresi, hex olarak 0x3a98 olup ondalık 15000 değerine karşılık gelmektedir. Bu değerin de 15 saniye olduğu düşünülebilir. Neden kesin yazmıyorum, çünkü CryptRetrieveObjectByUrlWithTimeout metodunun erişebildiğim bir dokümantasyonu yok. Rusça bir kaynakta geçen CryptRetrieveObjectByUrlW metodunun parametre sıralaması ile CryptRetrieveObjectByUrlWithTimeout  parametre sıralamasının en azından timeout değerine kadar aynı olduğunu varsaydım.

Windows, Authenticode kontrolü yapmak zorunda mı?

Windows’u bırakalım, .NET yapmak zorunda mı? .NET’te authenticode mekanizmasını baypas etmenin en az bir yolu var, o da app.config dosyasına yerleşecek bir adet generatePublisherEvidence anahtarı.

        <generatePublisherEvidence enabled="false"/>

Ama-fakat güvenlik? Microsoft, .NET uygulamalarında Authenticode yerine strong-name signing tavsiye ediyor.

Peki ya uygulamamız native windows uygulaması olsaydı?

Native windows uygulamalarında toptan çözüm olarak domain policyler ile gelebilen SRP ayarlarında değişikliğe gidilebilir. Bu değişiklik, Internet Explorer vasıtası ile de yapılabilir. İşaretli checkbox boş olmalıdır. Dikkat, bu ayar çalınmış sertifikaların kullanıldığı farklı güvenlik zafiyetlerine davetiye çıkartabilir.



Hangi URL Çağrılıyor?

Bir url çağrılıyor ama nasıl bir url, her uygulama hangi URL’i çağırıyor sorusunun cevabını alabilmek için CryptRetrieveObjectByUrlWithTimeout metodunun 3. parametresinin gösterdiği adrese unicode olarak bakmak yeterli.

0:000> du 00000000`199a7520
00000000`199a7520  ""
00000000`199a7560  "sdownload/update/v3/static/trust"
00000000`199a75a0  "edr/en/"

Hedef URL:

Not: Farklı URL’ler ile de karşılaşıldı.

Hangi Assembly Yüklenmek İstenirken Hata Alınıyor?

Peki bu URL’in çağrılmasına hangi assembly sebep olmuş? Proses imajı mı yoksa referans verilen assembly’lerden biri mi?

mscorsec modülünün GetPublisher metoduna verilen ilk parametreye baktığımızda zanlının Enterprise Library‘nin bir bileşeni olduğunu görüyoruz.

0:000> du 0000000`0028b7d0
00000000`0028b850  "crosoft.Practices.EnterpriseLibr"
00000000`0028b890  "ary.ExceptionHandling.dll"


Windows servisine yeni dahil edilen, Authenticode imzalı dll’lerden oluşan Enterprise Library 5.0 bileşenlerinin yüklenirken Authenticode sertifika geçersizlik listelerinin yüklenmek istenmesi neticesinde alınan zamanaşımının neden olduğu service controller zamanaşımı dolayısıyla, Enterprise Library 5.0 referansı olan hiç bir windows servis internet bağlantısı olmayan sunucumuzda çalışmıyordu.

Authenticode imza kontrolü, app.config’e generatePublisherEvidence anahtarı eklenerek baypas edildi.

  • “lokalde çalışıyor”: Windows servisinin geliştirme ortamında internet erişimi mevcut olduğunda Authenticode kontrolleri zamanaşımına yol açmıyordu.
  • “önceden çalışıyordu”: Uygulamada yapılan yükseltme ile Enterprise Library’nin 5.0 sürümüne geçildi. Bu geçişten önce dll’ler Authenticode imzalı olmadığından Authenticode kontrolü yapılmıyordu.
  • “başka sunucuda çalışıyor”: “Başka sunucu” internet erişimli olduğundan Authenticode kontrolü yapılmıyordu


git getir, git götür

Versiyon kontrol sistemi olarak svn, mercurial, bazaar ve git kullandıktan sonra en sorunsuz ve svn ile git-gel(roundtrip) kullanılabilen git’I tercih ettim. git’in komutlarından veya işleyişinden bahsedecek değilim, bu konularda pek çok makale bulabilirsiniz. Sadece kullandığım iki adet kısayolu paylaşmak istedim. Sıklıkla svn ile kullandığım git’te svn’deki değişiklikleri getirmek için ve yapılan değişiklikleri svn’e göndermek için aşağıdaki komutlar kullanılıyor.

  • Değişiklikleri getirmek için: git svn rebase
  • Değişiklikleri svn’e göndermek için: git svn dcommit

Bu komutları her sefer yazmak bir süre sonra banal olmaya başladı. git kullanırken kendi komut adlarınızı tanımlayarak varolan komutları çağırabilirsiniz.

Her ne kadar git’i git olarak okumak mübah olsa da aşağıdaki kısayolları ekledim ve kullanıyorum.

  • getir: svn rebase
  • gotur: svn dcommit

git getir ve git gotur yazdığınızda istediğiniz işlemler git tarafından zevkle yapılacaktır.

How (NOT) to Write a Patch for PostgreSQL


In this quick and dirty article, we will be describing a syntax and implementing the new syntax in postgresql backend. The syntax to be implemented is CORRESPONDING clause, which is referenced in the SQL20nn standard draft as “Feature F301, CORRESPONDING in query expressions”.

CORRESPONDING clause can be seen as a modifier for set operations in SELECT statements. It filters the projected columns to either match the same column names, or match the column names with a list (CORRESPONDING BY).

Note: [] denotes optionality

query1 and query2 are select statements.

query1 UNION [ ALL ] [ CORRESPONDING [ BY ( column_list ) ] ] query2

query1 EXCEPT [ ALL ] [ CORRESPONDING [ BY ( column_list ) ] ] query2

query1 INTERSECT [ ALL ] [ CORRESPONDING [ BY ( column_list ) ] ] query2

  • CORRESPONDING returns all columns that are in both query1 and query2with the same name.
  • CORRESPONDING BY returns all columns in the column_list that are also in both query1 and query2 with the same name.

We will use UNION operator, INTERSECT and EXCEPT works the same with CORRESPONDING clause. Here are some examples to clarify what CORRESPONDING means.

SELECT 1 a, 2 b, 3 c UNION CORRESPONDING SELECT 4 a, 5 b, 6 c;
 a | b | c 
 1 | 2 | 3
 4 | 5 | 6
(2 rows)

Now the fun part, we have removed column b from query2:

 a | c  
 1 | 3 
 4 | 6 
(2 rows)

SELECT 1 a, 2 b, 3 c UNION CORRESPONDING SELECT 4 d; ERROR: UNION queries with a CORRESPONDING clause must have at least one column with the same name

The idea with CORRESPONDING is, unmatched columns are removed. If no columns left to project, then it is a syntax error.

For the CORRESPONDING BY(column_list) part, one more step of filtering is done to ensure that columns in the column_list are present in query1 and query2.

SELECT 1 a, 2 b, 3 c UNION CORRESPONDING BY(a, b, c) SELECT 4 a, 5 b, 6 c;
 a | b | c 
 1 | 2 | 3
 4 | 5 | 6
(2 rows)

We remove a column name from column_list:

SELECT 1 a, 2 b, 3 c UNION CORRESPONDING BY(a, c) SELECT 4 a, 5 b, 6 c;
 a | c 
 1 | 3
 4 | 6
(2 rows)

Although we can suggest that CORRESPONDING BY is more useful with * queries as in:



There is a single main reason why I pursued to write a patch for CORRESPONDING in postgresql, I decided to delve into postgresql code base with a simple project and it was in the TODO list. As it turns out it is not simple, and I cannot go without the saying “If it is in the TODO list, it ain’t simple”.

Development Environment

After setting up a vmware virtual machine with Pardus Linux installed, complete all the updates and make sure you have at least the following software configuration.

  • Pardus Linux 2011.2 (kernel i686 GNU/Linux)
  • gcc 4.5.3 (compiler)
  • flex 2.5.35 (lexer)
  • bison 2.4.3 (parser generator)
  • autotools
  • gdb
  • ccache (compiler cache)
  • git (version control)
  • eclipse CDT (IDE)

For eclipse configuration please see:

For other details about setting up an environment for postgresql development, please see


In this section, we will touch to the very basics of postgres query execution relating to the execution of a set operation(UNION, INTERSECT, EXCEPT)

  1. Parser
    1. Raw Parser – Generate a raw parse tree from the sql statement.
    2. Analyzer – Generate a query tree from a raw parse tree. (This is what we will modify mostly)
  2. Optimizer – Choose an efficient plan.
  3. Executor – Execute the chosen plan.

How Exactly

There are two simple paths of implementing the CORRESPONDING clause, one is modifying the query tree such that query1 and query2 are wrapped in subqueries, and the other is modifying the way that UNION works which is a big deal involving many parts of the code from analyzer to optimizer. We chose to implement it by modifying the query tree which I will describe in a moment.

  1. Modify parser to accept new syntax.
    1. Introduce keywords.
    2. Generate a relevant parse tree for the set operation.
    3. Add metadata about CORRESPONDING operation to node structures in the raw parse tree. (column_list, is it CORRESPONDING or CORRESPONDING BY, etc.)
  2. Update analyzer to process the new syntax.
    1. While processing the set operation, verify validity of the CORRESPONDING semantics.
      1. Does the columns exist in both tables
      2. Is there any non-existent column names in column_list.
      3. Is output projection non-empty, etc.
    2. If CORRESPONDING clause is valid, modify query1 and query2.
  3. Write documentation.
  4. Write regressions.

Modifying parser is the easiest part, you would think. What is the big deal? We are only going to add a keyword, what could go wrong? Well, keep on.


gram.y is a bison grammar file. Bison produces a c file from this input. It’s syntax is intuitive and you will feel familiar if you check a few SQL statements you know by heart and inspect their gram.y counterparts. For the hasty it gram.y looks like this:

GrantStmt:	GRANT privileges ON privilege_target TO grantee_list
					GrantStmt *n = makeNode(GrantStmt);
					n->is_grant = true;
					n->privileges = $2;
					n->targtype = ($4)->targtype;
					n->objtype = ($4)->objtype;
					n->objects = ($4)->objs;
					n->grantees = $6;
					n->grant_option = $7;
					$$ = (Node*)n;

Here, uppercase words are keywords, lower case words are further definitions. statement between {} is the raw parse tree description of GrantStmt. privileges, privilege_target, grantee_list, opt_grant_grant_option are defined below this definition of GrantStmt.

Between the curly braces, we refer to the positional arguments of the statement.

n->privileges = $2;

$2 refers to privileges in the first line for example.


To use CORRESPONDING BY as a valid clause, we need to add CORRESPONDING and BY keywords to the parser. BY keyword is already used in GROUP BY, ORDER BY etc. so we only need to add CORRESPONDING token.

*** 498,504 ****
--- 499,505 ----

Add CORRESPONDING to select statement as a valid clause.

*** 8489,8507 ****
  					n->fromClause = list_make1($2);
  					$$ = (Node *)n;
! 			| select_clause UNION opt_all select_clause
! 					$$ = makeSetOp(SETOP_UNION, $3, $1, $4);
! 			| select_clause INTERSECT opt_all select_clause
! 					$$ = makeSetOp(SETOP_INTERSECT, $3, $1, $4);
! 			| select_clause EXCEPT opt_all select_clause
! 					$$ = makeSetOp(SETOP_EXCEPT, $3, $1, $4);

   * SQL standard WITH clause looks like:
--- 8490,8514 ----
  					n->fromClause = list_make1($2);
  					$$ = (Node *)n;
! 			| select_clause UNION opt_all opt_corresponding_clause select_clause
! 					$$ = makeSetOp(SETOP_UNION, $3, $4, $1, $5);
! 			| select_clause INTERSECT opt_all opt_corresponding_clause select_clause
! 					$$ = makeSetOp(SETOP_INTERSECT, $3, $4, $1, $5);
! 			| select_clause EXCEPT opt_all
! 					$$ = makeSetOp(SETOP_EXCEPT, $3, $4, $1, $5);
Now we need to define opt_corresponding_clause.
 			CORRESPONDING BY '(' expr_list ')'		{ $$ = $4; }
 			| CORRESPONDING							{ $$ = list_make1(NIL); }
 			| /*EMPTY*/								{ $$ = NIL; }

We have modified the parameter list of makeSetOp. Let’s go over there.

*** 12642,12648 ****

  static Node *
! makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg)

  	SelectStmt *n = makeNode(SelectStmt);

--- 12649,12655 ----

  static Node *
! makeSetOp(SetOperation op, bool all, List *correspondingClause, Node *larg, Node *rarg)

  	SelectStmt *n = makeNode(SelectStmt);

*** 12650,12655 ****
--- 12657,12663 ----
  	n->all = all;
  	n->larg = (SelectStmt *) larg;
  	n->rarg = (SelectStmt *) rarg;
+ n->correspondingClause = correspondingClause;

  	return (Node *) n;

Now that we have used SelectStmt->correspondingClause, let’s add it to parsenodes.h

*** 1006,1011 ****
--- 1006,1013 ----
  	 * These fields are used only in "leaf" SelectStmts.
+ List *correspondingClause; /* NULL, list of CORRESPONDING BY exprs, or */ + /* lcons(NIL, NIL) for CORRESPONDING */

Code will compile, but there is one tidbit missing. Postgres will shout an error to you about unrecognized keywords if you use a CORRESPONDING query.

You have to add all new keywords to kwlist.h

*** 94,99 ****
--- 94,100 ----


At this point we can compile postgres and see that it dismisses the CORRESPONDING or CORRESPONDING BY from a query without an error.


In transformSetOperationTree function, we determine the output column names, and verify their existence in tables of both sides. Here CORRESPONDING part is given. CORRESPONDING BY is similar.

else if(linitial(stmt->correspondingClause) == NULL)
	// CORRESPONDING clause, find matching column names from both tables. If there are none then it is a syntax error.

	Query	*largQuery;
	Query	*rargQuery;
	List	*matchingColumns;

	/* Analyze left query to resolve column names. */
	largQuery = parse_sub_analyze((Node *) stmt->larg, pstate, NULL, false);

	/* Analyze right query to resolve column names. */
	rargQuery = parse_sub_analyze((Node *) stmt->rarg, pstate, NULL, false);

	/* Find matching columns from both queries. */
	matchingColumns = determineMatchingColumns(largQuery->targetList,

	op->correspondingColumns = matchingColumns;
	op->hasCorrespondingBy = false;

	/* If matchingColumns is empty, there is an error. At least one column in the select lists must have the same name. */
	if(list_length(matchingColumns) == 0)
		ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),
						errmsg("%s queries with a CORRESPONDING clause must have at least one column with the same name",

	// Create subquery for larg, selecting column names from matchingColumns.
	stmt->larg = createSubqueryForCorresponding(matchingColumns, stmt->larg);

	// Assign newly generated query to original left query.
	op->larg = transformSetOperationTree(pstate, stmt->larg,

	// Create subquery for rarg, selecting column names from matchingColumns.
	stmt->rarg = createSubqueryForCorresponding(matchingColumns, stmt->rarg);

	// Assign newly generated query to original right query.
	op->rarg = transformSetOperationTree(pstate, stmt->rarg,

To create a subquery with given column names and a query to me used as a subquery, we use createSubqueryForCorresponding function. This function returns a SelectStmt for the following statement: “SELECT outputColumns FROM (main_arg)

 * Returns a subquery selecting outputColumns from main_arg.
 * main_arg is modified and returned.
static SelectStmt *
createSubqueryForCorresponding(List* outputColumns, SelectStmt* main_arg)
	ColumnRef *cr;
	ResTarget *rt;
	SelectStmt *n;

	RangeSubselect * rss;
	ListCell* mctl;

	n = makeNode(SelectStmt);
	n->targetList = NIL;
	foreach(mctl, outputColumns)
		TargetEntry *mctle = (TargetEntry *) lfirst(mctl);

		cr = makeNode(ColumnRef);
		cr->fields = list_make1(makeString(mctle->resname));
		cr->location = -1;

		rt = makeNode(ResTarget);
		rt->name = NULL;
		rt->indirection = NIL;
		rt->val = (Node *)cr;
		rt->location = -1;

		n->targetList = lappend(n->targetList, rt);

	rss = makeNode(RangeSubselect);

	// XXX makeAlias alias name should be empty??
	rss->alias = makeAlias("", NULL);
rss->subquery = (Node *)main_arg;

	n->fromClause = list_make1(rss);

	main_arg = n;

	return main_arg;

For documentation, please see changes in

  • doc/src/sgml/queries.sgml
  • doc/src/sgml/sql.sgml

For regression, please see the excellent article from postgresql, and see the changes in

  • src/test/regress/sql/corresponding_union.sql
  • src/test/regress/serial_schedule
  • src/test/regress/parallel_schedule
  • src/test/regress/expected/corresponding_union.out

The (not) part

This is the main reason the patch was not accepted by the postgresql community: When we modify the parse tree in the analyzer.c, we modify it for good. Optimizer, planner, executor never sees a CORRESPONDING clause, they only see the subquery we generated.


SELECT 1 a, 2 b, 3 c UNION CORRESPONDING BY(a, c) SELECT 4 a, 5 b, 6 c

=# select * from v1;
 a | c 
 1 | 3
 4 | 6
(2 rows)

=# select * from pg_views WHERE viewname = 'v1';
 schemaname | viewname | viewowner |                                                                  definition                                                                  
 public     | v1       | kerem     |

SELECT alias.a, alias.c FROM (SELECT 1 AS a, 2 AS b, 3 AS c) alias UNION SELECT alias.a, alias.c FROM (SELECT 4 AS a, 5 AS b, 6 AS c) alias

(1 row)

Patch File

KorTrans – UTM Koordinat ve Pafta (Android)

KorTrans – Koordinat Dönüşüm (Android)

Android telefonları için UTM, Derece Dakika Saniye, Ondalık Derece koordinat dönüşüm programı.

Android Market’ten indirmek için (ücretsiz): KorTrans aratabilir veya adresine doğrudan gidebilirsiniz.

Desteklediği Koordinat Türleri:

  • Universal Transverse Mercator (UTM, 6 derecelik, WGS84 datumu): 35T 555555 4600000
  • Derece Dakika Saniye (DDS, DMS): 41° 32′ 59,05″ K 27° 39′ 58,08″ D
  • Ondalık Derece (DD): 41,549735 K 27,666134 D


  • Pafta bulma.
  • Noktaları kaydedebilme
  • Kayıtlı noktalara simge, kod, not ve resim ekleyebilme.
  • Kayıtlı noktalar üzerinde manuel veya haritadan sürükleyerek oynama yapabilme
  • Kayıtlı noktaların resmini silebilme, değiştirebilme
  • Kayıtlı noktayı UTM veya DDS’ye dönüştürme
  • Kayıtlı noktaların tümünün koordinatlarını mail olarak gönderebilme
  • Koordinatları manuel girme
  • Haritadan nokta seçme
  • Haritadan nokta seçerken adrese göre arama (geocoding)
  • Haritadan seçilen noktanın adresini gösterme (reverse geocoding)
  • GPS yardımıyla nokta seçme

İleride Eklenecek Özellikler:

  • KorTrans kullanıcı adı ve şifresi ile noktaları cloud’a kaydetme, gönderme.
  • Noktalardan poligon oluşturma, kaydetme.
  • Poligon koordinatlarını ruhsat başvurusu için mail atma.
  • Ruhsatların alanlarını görüntüleme.
  • GPS yardımıyla fiziksel olarak ruhsat sahasında olup olmadığınızın tespiti.


Ondalık Dereceden UTM’ye Dönüşüm:

UTM’den Derece Dakika Saniyeye Dönüşüm:

Haritadan Seçilen Noktanın Dönüşümü:

Kayıtlı Noktaları Mail Atma:

Bir Polinomu İkinci Derece Başka Bir Polinoma Bölmede Kalan

Matematik ve polinomlar ile ilgili bu yazımızda karşılaşılan bir problemin analitik çözümüne kısaca değineceğiz.

Polinom kalan teoremine göre, P(x) polinomunun (x-a) binomuna bölümünden kalan, P(a)’dır. Diğer bir deyişle:

Polinom bölme.

P(x) polinomunun (x-a) binomuna bölümünden kalan A, (x-b) binomuna bölümünden kalan B olsun.

Bizden istenen P(x) polinomunun, (x-a)(x-b) polinomuna bölümünden kalandır. Problemi kısaca ifade edelim:

Polinom bölme.

Bildiklerimizi yerlerine koyalım:

A = P(a) = (a-a) \cdot (a-b) \cdot Q(x) + K(a) = K(a)

B = P(b) = (b-a) \cdot (b-b) \cdot Q(x) + K(b) = K(b)

\deg(K(x)) = 1 \implies K(x) = m \cdot x + n \ni m,n \in \mathbb{R}

A = m \cdot a + n

B = m \cdot b + n

A - B = m \cdot (a - b)

m = \frac{A-B}{a-b}

b \cdot A = m \cdot a \cdot b + b \cdot n

a \cdot B = m \cdot a \cdot b + a \cdot n

b \cdot A - a \cdot B = n \cdot (b-a)

n = \frac{b \cdot A - a \cdot B}{b-a}


Aşağıdakine benzer bir formülü tüm çabalarım neticesinde googleda bulamadım, belki de ne yazacağımı bilemediğimdendir…

K(x) = \frac{A-B}{a-b} \cdot x + \frac{a \cdot B - b \cdot A}{a-b}


P(x) polinomunun (x+2) binomuna bölümünden kalan 3, (x-4) binomuna bölümünden kalan -9’dir. P(x)’in (x+2)(x-4) polinomuna bölümünden kalan nedir?


a = -2

b = 4

A = 3

B = -9

Formülümüzde yerine koyalım:

K(x) = \frac{3- (-9)}{-2-4} \cdot x + \frac{(-2) \cdot (-9) - 4 \cdot 3}{ -2-4 }

K(x) = \frac{12}{-6} \cdot x + \frac{18-12}{-6}

CPU üzerinde Connected Component Labelling

Önceki CUDA ile OpenCV kullanarak Webcam Görüntü İşleme 
başlıklı yazımızda bahsedilen projeye ekleme bir filtre olarak gerçekleştirilen Connected Component Labeling (Birleşik Eleman Etiketleme) filtresini OpenCV ile webcam görüntü işlemede nasıl kullandığımıza bakalım.

NOT: Bu yazıdaki kod örnekleri kısaltılarak verilmiştir. Kod belgeleri için Doxygen ile yaratılmış olan mikrositeyi inceleyebilirsiniz (yazıdaki eklemeleri içerecek şekilde güncellenmiştir).

NOT: Her tür fikir, öneri ve eleştirinizi yorumlara yazabilirsiniz, teşekkür ederiz.


  • Gerekenler
  • CCL Nedir?
  • CCL için Önişleme
  • CPU CCL Filtresi: CpuCCLFilter
  • Filtre Örnekleri
  • İndirmeler


  • VS 2010 ve C/C++ Bilgisi
  • OpenCV ile görüntü yakalama aşinalığı. Windows için OpenCV 2.2’yi patchlemeyi unutmayın! Önceki yazımızı inceleyebilirsiniz.
  • VS2010 ile CUDA projesi yaratabilmek. Önceki yazımızı inceleyebilirsiniz.
  • CUDA içeren kodları çalıştırabilmek için CUDA destekli bir ekran kartı.
  • Derleyici includeları, libraryleri ve hataları ile uğraşmak için bolca sabır.
  • Önceki yazımızda detayları bulabilirsiniz: CUDA ile OpenCV kullanarak Webcam Görüntü İşleme

CCL Nedir?

Connected Components Labeling, görüntüde birleşik olan nesneleri etiketleyerek birbirinden ayırdedebilecek hale getiren algoritmaya verilen addır. Burada en önemli tanım, “görüntüde birleşik” tamlamasıdır. Bu filtredeki kodlar, wikipediadaki CCL açıklamasından yola çıkılarak yazılmıştır.

Görüntünün birleşik olması, komşu piksellerin renklerinin aynı veya belli bir derecede yakın olması ile ölçülür. Komşulukları gözönüne alırken 4-komşu ve 8-komşu modelleri kullanılabilir. 4-komşu modeli, ana yönler olan kuzey, güney, doğu ve batı komşularıdır. 8-komşu modelinde ara yönlerdeki komşular da hesaba katılır.



CCL için Önişleme

Renk Benzerliği

Renk benzerliği, CCL filtremizde birbiri ile aynı olarak nitelendirilecek renkleri ayırdetmemize yarar. Basit olarak gri skala uzayında uzaklığı 10’dan küçük olan renkler aynı sayıldı. Standart bir webcamin yakaladığı görüntülerde (en azından benimkinde) RGB noise denilen her renkten gürültü vardır. Webcam sabit bir yere bakarken ve görüntüde hiç hareket yokken bile yakalanan resmin pikselleri kısıtlı bir aralıkta sürekli değişir. Renklerin aynı olmasını katı bir şekilde gerektirmeyerek saptanan etiket sayısını düşürüyoruz, bir bakıma bu gürültüye bağışıklık kazanıyoruz.


Thresholding, belli bir aralığa sahip değeri, iki adet değere indirgemenin bir yoludur. Örneğin değerimiz 0 ile 255 arasında ise, threshold değerimiz 90 ise, 90’dan küçük değerler 0, büyük ve eşit değerler 1 grubuna denk gelir. CCL, threshold işlemi görmüş görüntü üzerinde çalışır. CCL algoritması için 0 arkaplan, 1 nesne demektir.

CPU CCL Filtresi: CpuCCLFilter

ISingleImageFilter arayüzünü kullanarak yazılan filtrede en önemli metod olan findConnectedComponents kısaca anlatılarak gösterilmiştir.

	\ref ptKernelLauncher tipinde metod.

	\param width Görüntünün piksel olarak genişliği
	\param height Görüntünün piksel olarak yüksekliği
	\param rowStride Görüntünün hafızadaki byte olarak genişliği.
	\param imageData Görüntü verisi.
	\param outImageData Etiket görüntü verisi.
	\param outLabelBitmap Etiket integer bitmap.

	Görüntüdeki birleşmiş birimleri bulur. Connected Component Labeler.
template<bool eightConnected>
void CpuCCLFilter::findConnectedComponents(int width, int height, int rowStride, char* imageData, char* outImageData, int* outLabelBitmap)
	// label bitmap	

	// disjoint set için tip ve map tanımları.
	typedef std::map<short, std::size_t> rank_t; // element order.
	typedef std::map<short, short> parent_t;

	rank_t rank_map;
	parent_t parent_map;

	boost::associative_property_map<rank_t>   rank_pmap( rank_map );
	boost::associative_property_map<parent_t> parent_pmap( parent_map );

	// disjoint sets yaratılır.
	boost::disjoint_sets<boost::associative_property_map<rank_t>, boost::associative_property_map<parent_t>> 
		ds( rank_pmap, parent_pmap );

	boost::unordered_set<short> elements;

	short labelNumber = 0;

	for(int i = 0; i < height; i++)
		for(int j = 0; j < width; j++)
			outLabelBitmap[i*rowStride + j] = 0;

	// tüm pikseller gezilir
	for(int i = 0; i < height; i++)
		for(int j = 0; j < width; j++)
			// if pixel is not background.
			if( imageData[i*rowStride + j] != 0 )
				if(j > 0 & i > 0 &
					isSameColor( imageData[i*rowStride + j - 1], imageData[(i - 1)*rowStride + j]) // same value
					& isSameColor( imageData[i*rowStride + j - 1], imageData[i*rowStride + j] )
					// west ve north aynı
					ds.union_set( outLabelBitmap[i*rowStride + j - 1], outLabelBitmap[(i - 1)*rowStride + j] );
					outLabelBitmap[i*rowStride + j] = outLabelBitmap[i*rowStride + j - 1];

				if(j==0 & i > 0 & isSameColor( imageData[i*rowStride + j], imageData[(i - 1)*rowStride + j] ))
					outLabelBitmap[i*rowStride + j] = outLabelBitmap[(i-1)*rowStride + j];

				// West pixel
				if(j > 0 & isSameColor( imageData[i*rowStride + j - 1], imageData[i*rowStride + j] ))
					// west pixel ile aynı label.
					outLabelBitmap[i*rowStride + j] = outLabelBitmap[i*rowStride + j - 1];

				// west farklı north aynı.
					(j > 0 & !isSameColor( imageData[i*rowStride + j - 1], imageData[i*rowStride + j] )) // west different value
					& (i > 0 & isSameColor( imageData[(i-1)*rowStride + j], imageData[i*rowStride + j] )) // north same value					
					// north ile aynı
					outLabelBitmap[i*rowStride + j] = outLabelBitmap[(i-1)*rowStride + j];					

				// west ve north farklı
				if(   ((j > 0 &;amp;& !isSameColor( imageData[i*rowStride + j - 1], imageData[i*rowStride + j] )) || j == 0) // west different value
					& ((i > 0 & !isSameColor( imageData[(i-1)*rowStride + j], imageData[i*rowStride + j] )) || i == 0) // north different value					
					outLabelBitmap[i*rowStride + j] = labelNumber;

				// northeast ve northwest kontrol edilir. (çaprazlar).
					// northwest
					if(j > 0 & i > 0
						& isSameColor( imageData[(i-1)*rowStride + j - 1], imageData[i*rowStride + j] )
						// northwest ile aynı
						ds.union_set( outLabelBitmap[(i-1)*rowStride + j - 1], outLabelBitmap[i*rowStride + j] );

					// northeast
					if(j+1 < width & i > 0
						& isSameColor( imageData[(i-1)*rowStride + j + 1], imageData[i*rowStride + j] )
						// northeast ile aynı
						ds.union_set( outLabelBitmap[(i-1)*rowStride + j + 1], outLabelBitmap[i*rowStride + j] );

	int cnt = ds.count_sets(elements.begin(), elements.end());

	printf("Component count: %i\n", cnt);

	// second pass - label output image and colorize.
	for(int i = 0; i < height; i++)
		for(int j = 0; j < width; j++)
			int labelNo = ds.find_set( outLabelBitmap[i*rowStride + j] ); // pikselin etiketi bulunur.
			int R =0, G=0, B=0;

			// etiketler renklendirilir.
			hsl_to_rgb( 1.0f * labelNo / labelNumber, .8f + .2f * labelNo / labelNumber, .75f, &R, &G, &B );

			int idx = i * rowStride + j;

			outImageData[idx * 3 + 0] = (char)(B);
			outImageData[idx * 3 + 1] = (char)(G);
			outImageData[idx * 3 + 2] = (char)(R);


Filtre Örnekleri



Dosyalar 7-zip ile sıkıştırılmıştır.

UTM Koordinat Sistemi ve Türkiye Paftaları

Koordinat Dönüşümü ve Paftalar

Serbestçe kullanabileceğiniz bir silverlight uygulaması olan KorTrans SL v1.0’a bu linkten erişebilirsiniz.

  • Tüm Türkiye’deki paftaları, haritadan nokta seçerek bulabilirsiniz.
  • UTM, Derece-Dakika-Saniye ve Ondalıklı Derece sistemleri arasında dönüşüm yapabilirsiniz.
  • Pafta ismini “İSTANBUL-F22-b3” veya “F22-b3” şeklinde girerek de paftayı bulabilirsiniz.
  • Seçilen pafta üzerinde UTM grid çizgilerini gösterebilirsiniz.
  • Ölçeğinize göre belirlenen komşu paftaları görebilirsiniz.Her zamanki gibi değerli yorumlarınızı bekliyoruz.

Program silverlight ile çalışır. Silverlight, Microsoft’un bir platformudur, yüklemek çok kolaydır.

KorTrans SL


Programda markeri sürükleyerek koordinatı belirlersiniz.

Not: Sol üst köşedeki dönüşüm fonksiyonlarını denemeyi unutmayın!


KorTrans SL:

OpenCV ile WebCam Görüntüsü İşleme

OpenCV Nedir?

OpenCV, açık kaynaklı bir bilgisayarlı görselleştirme kütüphanesidir. Amacı görüntü işleme ve görselleştirmede sık kullanılan metodların kolaylıkla erişilebilir olmasını sağlamaktadır. Yazımızda kullandığımız OpenCV 2.2 ile webcam görüntüsü işlerken bu kolaylığı farkedeceğiz.

Webcam görüntüsünü alacağım derseniz bir yolu da DirectShow kullanmaktır ki bu yol uzun ince bir yoldur, bkz. DirectShow Webcam

Webcam Görüntüsünü Almak

Yüklü ve windows tarafından tanınmış olan webcaminizden OpenCV kullanarak görüntü almak için yazmanız gereken kod sadece tek bir satırdır.

CvCapture* capture = 0;
capture = cvCaptureFromCAM(0);
IplImage* videoFrame = NULL;

videoFrame = cvQueryFrame(capture); // kameradan görüntü alınır


  • VS 2010 ve C/C++ Bilgisi
  • OpenCV 2.2 Kurulumu
  • OpenCV’yi kendiniz patchlemek isterseniz:
    • CMake, OpenCV’yi patchledikten sonra build etmek için.
    • OpenCV 2.2 Windows webcam patchi: İngilizce
  • Patchli dll ve libleri indirmek isterseniz:

İzlenen Yol

OpenCV 2.2 Patch

OpenCV 2.2 sürümünde mevcut olan bir bug, windows makinalarda görüntü alınmasına engel olmaktadır. Bu bugın varlığını keşfedinceye kadar bilgisayarımdan ve kameramdan şüphe etmiştim, neyseki şüphelerim yersizmiş. Patch deyince gözünüz korkmasın, sadece tek bir dosyada iki satır değişiklik yapmak gerekiyor. Bu satırlar için bkz. OpenCV 2.2 patch.

Yok ben dosyalarımı patchli kullanırım derseniz İndirmeler bölümünden OpenCV patch dosyasını indirip içindeki dll dosyalarını c:\opencv2.2\bin içerisinde, lib dosyalarını da c:\opencv2.2\lib dizinine oradaki dosyaların üzerine yazarak kopyalayabilirsiniz.

Visual Studio Projesi

  • Empty Win32 Console Project yaratarak yolculuğumuza başlıyoruz.
  • Projemizin özellik sayfasında VC++ Directories’de includeları ekliyoruz:
  • Projemizin özellik sayfasında VC++ Directories’de libraryleri ekliyoruz:
  • Kullanacağımız kütüphane dosyalarını Linker->Input->Additional Dependencies’e ekliyoruz.
  • Yaratacağımız main.h dosyasına içeriği ekliyoruz:
    #pragma once // Header dosyasına birden fazla referans olsa bile sadece 1 kere işlensin.
    #include <stdio.h>
    #include <stdlib.h>
    #include "opencv2\opencv.hpp"
  • Yaratacağımız main.cpp dosyasına webcamden capture edip görüntüyü negatif yaparak ekranda göstermeye yarayacak aşağıdaki kodu ekliyoruz.

Gerçek Zamanlı Webcam Negatifi


Dosyaları açabilmek için farklı kaydederek uzantısını 7z yapınız.
Patchlenmiş OpenCV dosyaları: OpenCV2.2 webcam patch
Örnek Proje Kaynakları: HelloOpenCV